Capistrano 3 Runit Support
cap-runit provides a helper for building runit services. It lets you easily deploy services using capistrano 3 and run them with runit.
Installation
Using bundler: Add gem 'cap-runit'
to your Gemfile
and require 'bundler';
Bundler.require
to your Capfile
.
Not using bundler: gem install cap-runit
and add require 'capistrano/runit'
to your Capfile
.
Usage
cap-runit provides a helper method runit_service
to Capistrano. As the
philosophy of runit is that everything is just a shell script, cap-runit
requires you to write a shell script.
For example, to run sidekiq, you might do something like this:
runit_service 'sidekiq' do
run <<-EOF
#!/bin/bash
cd /var/www/app/current
exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
EOF
end
This creates three capistrano tasks:
cap sidekiq:restart # Restart bugsnag-event-server
cap sidekiq:start # Start bugsnag-event-server
cap sidekiq:stop # Stop bugsnag-event-server
If you'd like to restart sidekiq when your app restarts, you also need to specify:
namespace :deploy do
after :publishing, 'sidekiq:restart'
end
Logging
Runit sends the STDOUT of your run
script to the log
script. To get these
logs somewhere useful, you can use any program that reads from STDIN. But
svlogd
is recommended as it works well with runit and handles log rotation
automatically.
runit_service 'sidekiq' do
run <<-EOF
#!/bin/bash -l
cd /var/www/app/current
exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
EOF
log <<-EOF
#!/bin/sh
mkdir -p /var/log/sidekiq
exec svlogd -tt /var/log/sidekiq
EOF
end
Crash notifications
If you need to be notified of when a crash happens in your app, you can also
configure a finish
script. This is run whenever the run
script exits.
runit_service 'sidekiq' do
run <<-EOF
#!/bin/bash -l
cd /var/www/app/current
exec bundle exec sidekiq -e production -C ./config/sidekiq.yml 2>&1
EOF
log <<-EOF
#!/bin/sh
mkdir -p /var/log/sidekiq
exec svlogd -tt /var/log/sidekiq
EOF
finish <<-EOF
#!/bin/sh
export BUGSNAG_API_KEY=bf04f47b034e8df9d22ee75f30fdae6a
[ "$1" = 0 ] || exec bugsnag-runit "$0"
EOF
end
Configuration
The only configuration variable you need to pass is runit_service_directory
set :runit_service_directory, "/apps/service"
The service directory needs to be run with runsvdir
and owned by the
capistrano user. To configure runsvdir
you can create the following files:
#/etc/service/cap-runit/run
#!/bin/bash
exec chpst -udeploy -- runsvdir /apps/service 2>&1
And
#/etc/service/cap-runit/log/run
#!/bin/sh
exec svlogd -tt /var/log/cap-runit
These files should both be owned by root and chmod +x
. This way the deploy
user does not need root permissions to reboot a service on deploy.