Using capistrano unicorn with multistage environment

Adam Spiers edited this page Aug 22, 2013 · 3 revisions

PLEASE NOTE: the previous version of this wiki page contained misleading information about the :app_env variable, due to a bug with how it was used. This is being addressed by pull request #70.

The issue is that capistrano loads default configuration and then executes your staging task and overrides previously defined variables. The default environment before executing stage task is set to :production, so it will use a wrong environment unless you take steps to ensure that :rails_env and :unicorn_env are set correctly.

Let's take a look at sample config/deploy.rb file:

set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'

You’ll need to add config/deploy/staging.rb and config/deploy/production.rb files. One way to do this is to explicitly set the per-environment variables in each of these files:

set :domain,      "YOUR_HOST"
set :rails_env,   "staging"
set :unicorn_env, "staging"

role :web, domain
role :app, domain
role :db,  domain, :primary => true

set :deploy_to,   "/home/#{user}/#{application}/#{fetch :rails_env}"
set :current_path, File.join(deploy_to, current_dir)

This should fix the problem with wrong rails env being passed to unicorn server. However, this violates DRY since a lot of these lines will be identical in each staging file. So it would be nicer to keep common settings in config/deploy.rb, and only put stuff in each staging definition file which is really specific to that staging environment. Fortunately this can be done using the lazy evaluation form of set. So instead config/deploy.rb file would contain something like:

set :stages, %w(production staging)
set :default_stage, "staging"
require 'capistrano/ext/multistage'

set(:unicorn_env) { rails_env }

role(:web) { domain }
role(:app) { domain }
role(:db, :primary => true) { domain }

set(:deploy_to)    { "/home/#{user}/#{application}/#{fetch :rails_env}" }
set(:current_path) { File.join(deploy_to, current_dir) }

and config/deploy/staging.rb would only need to contain:

set :domain,      "YOUR_HOST"
set :rails_env,   "staging"

Much cleaner!

Original Blogpost: http://blog.sosedoff.com/2012/01/21/using-capistrano-unicorn-with-multistage-environment/