HOWTO setup multistage deployment with Capistrano

These instructions are outdated. They were written for Capistrano 2.x. As of March 2016, Capistrano 3.x is current.

When I wrote about deploying PHP sites with Capistrano, step 6 was a bit of a throwaway — hey, here's a quick hack for handling multistage deployment. I'd been using variants of that technique for quite some time but figured there must be a better way. There is: Capistrano multistage. There is even documentation for this. But it misses a few steps.

How to setup multistage deployment with Capistrano

  1. Install capistrano and capistrano multistage
  2. Capify your project
  3. Set up the deploy/ directory
  4. Create the deployment recipes

In my Rails-based example, we'll have two stages: staging and production. You can name your stages whatever you want. However, don’t name one of your stages stage — that's a reserved word. Call it staging.

Install capistrano and capistrano multistage

gem install capistrano
gem install capistrano-ext

Capify your project

capify .

Set up the deploy directory

mkdir config/deploy
touch config/deploy/staging.rb
touch config/deploy/production.rb

Create the deployment recipes

You’re going to edit three files: deploy.rb, staging.rb and production.rb:

deploy.rb

set :stages, %w(staging production) set :default_stage, "production" require 'capistrano/ext/multistage'
default_run_options[:pty] = true
set :application, "myproject" set :use_sudo, false set :keep_releases, 5
set :repository, "https://somewhere/svn/myproject/trunk" set :scm, :subversion set :scm_username, "me" set :deploy_via, :export
# this is useful in a shared hosting environment, where you have your own JAVA_HOME or GEM_HOME. # otherwise, just set RAILS_ENV set(:rake) { "JAVA_HOME=#{java_home} GEM_HOME=#{gem_home} RAILS_ENV=#{rails_env} /usr/bin/env rake" }
# since :domain is defined in another file (staging.rb and production.rb), # we need to delay its assignment until they're loaded set(:domain) { "#{domain}" } role(:web) { domain } role(:app) { domain } role(:db, :primary => true) { domain }
namespace :deploy do task :start do ; end task :stop do ; end task :restart, :roles => :app, :except => { :no_release => true } do run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}" end end
# for some reason, this isn't enabled by default after "deploy:update", "deploy:cleanup"
# here is an example task which uses rake, as defined above after "deploy:migrate", "load_sample_fixtures" desc "load sample fixtures" task :load_sample_fixtures do run "cd #{current_release}; FIXTURES=samples #{rake} db:fixtures:load" end

staging.rb

set :deploy_to, "/path/to/#{application}-stage" # My Rails app uses RJB, so it needs to know where Java lives set :java_home, "/path/to/java-6-openjdk" set :domain, "testing.myserver.ca" set :user, "paul" set :rails_env, "staging" # I am root on my staging server and have all the right gems installed # so I don't need GEM_HOME to be overridden set :gem_home, nil

production.rb

set :deploy_to, "/home/myuser/#{application}" set :java_home, "/home/myuser/sw/jdk" set :domain, "www.myserver.ca" set :user, "myuser" set :rails_env, "production" set :gem_home, "/home/myuser/ruby/gems/"
# in a shared hosting environment, you often need to specify your own passenger configuration desc "copy the .htaccess file (passenger configuration); setup_load_paths.rb (sets GEM_HOME)" namespace :deploy do task :copy_htaccess do run "cp #{current_release}/config/htaccess_production #{current_release}/public/.htaccess" run "mv #{current_release}/config/production_setup_load_paths.rb #{current_release}/config/setup_load_paths.rb" end end
after "deploy:update_code", "deploy:copy_htaccess"

Now, you’re set. You can deploy with cap deploy (for the default stage, production), or cap staging deploy. TextMate's Capistrano plugin handles this gracefully, presenting you with a dialog listing the available stages.

11 Responses to HOWTO setup multistage deployment with Capistrano

  1. Hi Paul,
    Thanks for the post, really useful. It would have been perfect for my if I didn’t spend an hour figuring out why it was running the staging server in production env. I found somewhere else that the apache config needed “RailsEnv staging” within the VirtualHost.
    Thought it might be useful to others.
    Thanks again!

  2. Kris says:

    @Marc You can alternatively put “RailsEnv staging” in public/.htaccess that is likely what the copy_htaccess task is for :)

  3. paul says:

    Kris: exactly!

  4. Pingback: Ambienti di sviluppo multipli con Capistrano | FAndrea

  5. Steven says:

    I seem to be having issues with the “:primary => true” part of the :db role. My deploy.rb file contains the following…
    (destination is set in the miltistage files)


    set (:domain) {"#{destination}.#{application}.com"}
    role (:app) {domain}
    role (:web) {domain}
    role (:db, :primary => true) {domain}

    And I’m getting the following error…


    /Users/sjf/.rvm/gems/ruby-1.9.3-p194/gems/capistrano-2.13.4/lib/capistrano/configuration/loading.rb:93:in `instance_eval': ./config/deploy.rb:25: syntax error, unexpected ',', expecting ')' (SyntaxError)
    role (:db, :primary => true) {domain}
    ^

  6. What version of Ruby are you using? Do you need to use the Ruby 1.9 hash syntax?

  7. Steven says:

    ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]

    Turns out this works…

    role :db, :primary => true do
    domain
    end

    It doesn’t matter if I use “:primary => true” or “primary: true” it behaves the same. However, as soon as I put the parens around “:db, :primary => true” or replace do/end with {} the syntax fails.

  8. Sk Rajesh says:

    Hi,
    After execute ‘cap staging deploy’ I am getting the following error:
    capistrano/ext/multistage requires Capistrano 2

    why it happening? please help me regarding this.

  9. Sk Rajesh says:

    I’m installed ruby 2.2.4 – p230, capistrano-3.4.0 and capistrano-ext-1.2.1 for this.

  10. These instructions are for Capistrano 2. You have Capistrano 3. You need newer instructions. I’ve updated the article to indicate that it is now outdated.

  11. Sk Rajesh says:

    Thanks for your reply.
    So what is the newer instructions for Capistrano 3 ? Can you help me for new instructions?

Leave a Reply

Your email address will not be published. Required fields are marked *