Lugo Labs

Deploy Ruby on Rails apps with Capistrano

I really like Capistrano; it provides enough automation to my Rails apps, that I don't have to worry about gems, database migration, pre-compiling assets, restart job processors like Sidekiq, etc..

Setting up Capistrano is quite easy. It's best to have SSH access to our server via SSH keys (Github has a nice walkthrough on this). This allows running Capistrano without the need to input the password. I also setup the server's SSH keys in my source control server, in my case Bitbucket for git (I use Digital Ocean as server host).

Gemfile

Let's start by adding the necessary gems to our app's Gemfile.

ruby
group :development do
  gem 'capistrano', require: false
  gem 'capistrano-rails'
  gem 'capistrano-bundler'
  gem 'capistrano-rvm'
end

We use rvm to manage the Ruby versions in the server, hence the capistrano-rvm gem.

Update gems by running:

sh
bundle

Then install Capistrano by running the command:

sh
cap install .

This creates a few files for us, starting with the Capfile.

Capfile

Here we load any functionality we need for our deployment:

ruby
# Capfile

# Load DSL and set up stages
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Please note that capistrano/bundler will take care of bundling our gems in the server, and isolating them; capistrano/rails/assets will pre-compile the assets; and capistrano/rails/migrations will run the migrations.

Deploy

Another file that Capistrano generates for us is config/deploy.rb. For our basic deployment it sets the following options:

ruby
set :application,   '[APPLICATION NAME]'
set :format,        :pretty
set :log_level,     :debug
set :pty,           true
set :linked_files,  %w{config/database.yml}
set :linked_dirs,   %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
set :keep_releases, 3
set :rails_env,     'production'
set :repo_url,      '[GIT REPO URL]'
set :scm,           :git
set :branch,        'master'

The linked files are usually secure files we don't hold into our source control (e.g. git). database.yml is such a file, so we need to create that manually in the server. In fact if we run deploy:check now, Capistrano will tell us where to add the database.yml file:

sh
cap production deploy:check

Every time we run the cap command, we must specify the deployment stage, e.g. staging or production. Capistrano creates files for each of them inside config/deploy folder. The production.rb file could look like this (replace the square braces with your own settings):

ruby
set :stage,     :production
set :deploy_to, '[SERVER DIRECTORY]'
server '[SERVER IP ADDRESS/URL]', user: '[SERVER USER]', roles: %w{web app db}

If the deploy:check command runs without problem, we can finally deploy our app to the server:

sh
cap production deploy

We may need to fix any errors that this command will return, in my experience, mostly due to security settings.

Conclusion

We walked through a basic Rails app deployment with Capistrano. But Capistrano can do much, much more, such as setting up/restarting the web server (e.g. nginx), monitoring system (e.g. monit), queue processor (e.g. Sidekiq), etc..

Happy deployment!