Applikatoni is a self-hosted deployment server for small teams, that takes your code from GitHub and deploys it to your servers, by running shell commands you define.
Applikatoni was developed at flinc for internal use and later open sourced.
With its web-frontend and its deep GitHub integration it allows you to deploy your applications to multiple servers with the click of a button.
Besides giving your team a history of deployments, so you can see what has been deployed by whom to which servers, it also offers integration into a multitude of a third-party services, so your team never misses a deployment. Deploy pull requests from GitHub, check the Travis CI status of a branch before deploying, notify your team in Flowdock or Slack about deployments, tell NewRelic about the current revision of your application and reset Bugsnag after a deployment.
No database server is needed. Applikatoni stores information about deployment in a sqlite3 file. Easy to use, easy to maintain and easy to backup.
At its core, Applikatoni is technology agnostic. Deploy Rails, Node.js, Java and Go applications. It doesn't matter to Applikatoni. It doesn't do more than taking your code from GitHub and deploying it to your servers by running the shell commands you specify.
You can run different scripts on different hosts, if they fulfill different roles in your system. Your application server may need to run different commands than your background worker server, or your database server. Applikatoni can handle all of this.
With the ability to deploy multiple applications to different servers with varying deployment strategies you can use Applikatoni however you like.
And if clicking isn't your thing and you prefer a terminal over a web frontend: check out toni -- the CLI for your Applikatoni server.
Also: there is a lot of pizza involved! 🍕
Create a GitHub Application for your organization so Applikatoni can access your code:
https://github.com/organizations/<YOUR ORGANIZATION>/settings/applications
Enter the OAuth2 callback URL:
<where your applikatoni instance will be hosted>/oauth2/callback
Install Applikatoni on your server. See Installation for more information
Configure Applikatoni. See Configuration for detailed instructions.
Setup the database with the packaged goose binary. See Usage on how to do that.
Start Applikatoni
See the Releases section and download a packaged version of Applikatoni.
go get go get github.com/applikatoni/applikatoni/server
go get bitbucket.org/liamstask/goose/cmd/goose
vim db/dbconf.yml
goose -env="production" up
Create a configuration.json file for your needs. See Configuration for more information.
cp configuration_example.json configuration.json vim configuration.json 3. Start the server:
./applikatoni -port=:8080 -db=./db/production.db -conf=./configuration.json -env=production
Applikatoni is a server with a web-frontend that allows users to deploy specific commits hosted on GitHub to multiple servers.
A deployment process consists of multiple stages, which Applikatoni will
execute sequentially on each server, but at the same time on all servers.
A stage is nothing more than a few lines of shell commands, that you specify.
These shell commands can contain variables, like CommitSha, RubyVersion,
WorkingDirectory and so on. Before the deployment process starts, Applikatoni
"renders" these scripts templates into fully executable commands, by injecting
the values of the variables.
With the templates fully rendered, Applikatoni then connects to the specified servers via SSH (and a username and private SSH key you specify) and executes these shell commands.
If one stage fails, the whole deployment process is stopped after the failed stage has finished on all servers, so there is no inconsistent state.
Which stages are executed on which servers depends on which roles each server
fulfills in your system. If the server one.your-company.com has the role
"application-server" and two.your-company.com has the role "queue-server" only
the stages specified for the respective stages get executed on the servers.
Here is an excerpt from an example configuration.json:
"default_stages": ["PRE_DEPLOYMENT", "CODE_DEPLOYMENT", "POST_DEPLOYMENT"],
"available_stages": ["PRE_DEPLOYMENT", "CODE_DEPLOYMENT", "MIGRATE_DATABASE", "POST_DEPLOYMENT"],
"hosts": [
{
"name": "web.shipping-company.com:22",
"roles": ["web", "migrator"]
},
{
"name": "workers.shipping-company.com:22",
"roles": ["workers"]
}
],
"roles": [
{
"name": "workers",
"script_templates": {
"PRE_DEPLOYMENT": "sudo /etc/init.d/workers stop",
"CODE_DEPLOYMENT": "cd {{.Dir}}/current && git fetch origin && git reset -q --hard {{.CommitSha}}",
"POST_DEPLOYMENT": "sudo /etc/init.d/workers start"
},
"options": {
"Dir": "/var/www/our-main-application"
}
},
{
"name": "web",
"script_templates": {
"PRE_DEPLOYMENT": "sudo /etc/init.d/application-server prepare",
"CODE_DEPLOYMENT": "cd {{.Dir}}/current && git fetch origin && git reset -q --hard {{.CommitSha}}",
"POST_DEPLOYMENT": "sudo /etc/init.d/application-server reload"
},
"options": {
"Dir": "/var/www/our-main-application"
}
},
{
"name": "migrator",
"script_templates": {
"MIGRATE_DATABASE": "cd {{.Dir}} && make migrate-database"
},
"options": {
"Dir": "/var/www/our-main-application",
}
}
]
The web.shipping-company.com host has the roles web and migrator. The
workers.shipping-company.com host has the role workers.
With a default deployment, the stages PRE_DEPLOYMENT, CODE_DEPLOYMENT and
POST_DEPLOYMENT will be run on those two hosts.
If you also select MIGRATE_DATABASE before creating the deployment, the stages
PRE_DEPLOYMENT, CODE_DEPLOYMENT, MIGRATE_DATABASE and POST_DEPLOYMENT
will be run on those two hosts. In this order. And since
workers.shipping-company.com doesn't fulfill the migrator role, the
MIGRATE_DATABASE stage will be skipped on this server.
Before running the commands, Applikatoni converts this:
cd {{.Dir}}/current && git fetch origin && git reset -q --hard {{.CommitSha}}
into this:
cd /var/www/our-main-application/current && git fetch origin && git reset -q --hard F00B4R
where F00B4R is the commit SHA you selected in the web frontend.
application - Applikatoni can deploy multiple applicationstarget - The target environment of a deployment, e.g.: productionhost - Each target has one or more hosts, the servers to which to deploy
to. e.g.: web-application.production.shipping-company.comrole - Every host of each target fulfills different roles. What gets
executed and when on which host depends on the roles this host has. e.g.:
database-server or web-app-server.stage - A deployment consists of one or more stages. A role defines one or
more stages (by defining script_templates for each stage). A stage can
succeed or fail while deploying the application. If a stage failed, the
deployment stops after this change. All stages are executed synchronously on
all hosts (but in parallel).The Applikatoni is configured by reading a configuration.json file.
You can find a simplified example for a Rails application with two Unicorn web servers and one Sidekiq worker server here: configuration_example.json. Or read on to get a run down of what it's doing.
Here is a sample configuration.json for an application called
our-main-application with its source code hosted under
github.com/shipping-company/our-main-application.
The application will be deployed to three servers:
The deployment process reflects one of a typical Rails application with the Unicorn webserver and Sidekiq as a background worker process.
CommitSha variable is injected by
Applikatoni into the script templates and represents the commit the user
wants to deploy){
"ssl_enabled": false,
"host": "applikatoni.shipping-company.com",
"session_secret": "<SECRET>",
"oauth2_state_string": "<UNGUESSABLE RANDOM OAUTH2 STATE STRING>",
"github_client_id": "<CLIENT_ID>",
"github_client_secret": "<CLIENT_SECRET>",
"mandrill_api_key": "<API_KEY>",
"applications": [
{
"name": "our-main-application",
"read_usernames": ["<CAN READ DEPLOYMENT HISTORY BUT NOT DEPLOY>"],
"github_owner": "shipping-company",
"github_repo": "our-main-application",
"github_branches": ["master", "develop", "production", "production"],
"travis_image_url": "https://magnum.travis-ci.com/shipping-company/our-main-application.svg?token=<KEY HERE>",
"daily_digest_receivers": ["team@shipping-company.com"],
"daily_digest_target": "production",
"targets": [
{
"name": "production",
"deployment_user": "deploy",
"deployment_ssh_key": "<SSH KEY>",
"deploy_usernames": ["<YOUR GITHUB USERNAME>"],
"default_stages": ["CHECK_CONNECTION", "PRE_DEPLOYMENT", "CODE_DEPLOYMENT", "POST_DEPLOYMENT"],
"available_stages": ["CHECK_CONNECTION", "PRE_DEPLOYMENT", "CODE_DEPLOYMENT", "MIGRATE_DATABASE", "POST_DEPLOYMENT"],
"bugsnag_api_key": "<YOUR BUGSNAG API KEY>",
"flowdock_endpoint": "<FLOWDOCK REST ENTRY POINT WITH HTTP AUTH>",
"new_relic_api_key": "<NEW RELIC API KEY>",
"new_relic_app_id": "<NEW RELIC APP ID>",
"slack_url": "<SLACK INCOMING WEBHOOK URL>",
"webhooks": [
{
"url": "<URL>",
"entries": ["<ENTRYTYPE>"]
}
],
"hosts": [
{
"name": "1.unicorn.production.shipping-company.com:22",
"roles": ["web", "migrator"]
},
{
"name": "2.unicorn.production.shipping-company.com:22",
"roles": ["web"]
},
{
"name": "1.workers.production.shipping-company.com:22",
"roles": ["workers"]
}
],
"roles": [
{
"name": "workers",
"script_templates": {
"CHECK_CONNECTION": "test -d {{.Dir}}",
"PRE_DEPLOYMENT": "sudo /etc/init.d/sidekiq stop",
"CODE_DEPLOYMENT": "cd {{.Dir}}/current && git fetch --tags -q origin && git reset -q --hard {{.CommitSha}}\ncd {{.Dir}}/current && RAILS_ENV={{.RailsEnv}} bundle install --gemfile {{.Dir}}/current/Gemfile --path {{.Dir}}/shared/bundle --deployment --quiet --without development test",
"POST_DEPLOYMENT": "sudo /etc/init.d/sidekiq start"
},
"options": {
"Dir": "/var/www/our-main-application",
"RailsEnv": "production"
}
},
{
"name": "web",
"script_templates": {
"CHECK_CONNECTION": "test -d {{.Dir}}",
"PRE_DEPLOYMENT": "echo 'Unicorn will keep on working'",
"CODE_DEPLOYMENT": "cd {{.Dir}}/current && git fetch --tags -q origin && git reset -q --hard {{.CommitSha}}\ncd {{.Dir}}/current && RAILS_ENV={{.RailsEnv}} bundle install --gemfile {{.Dir}}/current/Gemfile --path {{.Dir}}/shared/bundle --deployment --quiet --without development test",
"POST_DEPLOYMENT": "sudo /etc/init.d/unicorn hot-reload"
},
"options": {
"Dir": "/var/www/our-main-application",
"RailsEnv": "production"
}
},
{
"name": "migrator",
"script_templates": {
"MIGRATE_DATABASE": "cd {{.Dir}} && RAILS_ENV={{.RailsEnv}} bundle exec rake db:migrate"
},
"options": {
"Dir": "/var/www/our-main-application",
"RailsEnv": "production"
}
}
]
}
]
}
]
}
ssl_enabled - Turn this on if your Applikatoni instance is
accessed via https.host - The host of your Applikatoni instance. Example:
applikatoni.shipping-company.comsession_secret - The secret for encrypt sessions in cookies. Use a
generated, random secret.$ claude mcp add applikatoni \
-- python -m otcore.mcp_server <graph>