David Dollar


Deploying a Rails Application with Capistrano

In most of the apps I work on regularly, the Capistrano setup has become a ungainly monster that has evolved over time and over multiple Capistrano and Rails versions. Participating in the Rails Rumble has given me an opportunity to set up a Capistrano configuration from scratch.

This is what I came up with. It will automatically handle the following:

  • SQLite databases stored in shared/db will be carried across releases
  • Configuration files stored in shared/config will be symlinked into config
  • Automatically install all Rubygems needed by the application
  • Restart via Passenger's tmp/restart.txt
set :application, "application-name"
set :deploy_to,   "/srv/app/#{application}"
set :deploy_via,  :remote_cache
set :repository,  "git@example.org:application.git"
set :scm,         "git"
set :user,        "deploy"

default_run_options[:pty]   = true
ssh_options[:forward_agent] = true

role :app, "server.example.org"
role :db,  "server.example.org", :primary => true

namespace :deploy do
  desc "Restart Application"
  task :restart do
    run "touch #{current_path}/tmp/restart.txt"
  end
end

namespace :gems do
  desc "Install Gems"
  task :install do
    run "cd #{release_path} && sudo env RAILS_ENV=production rake gems:install"
  end
end

namespace :shared do
  desc "Link shared config files"
  task :configuration do
    run %{
      for FILE in $(ls #{shared_path}/config);
      do
        ln -sf #{shared_path}/config/$(basename $FILE) #{release_path}/config/$(basename $FILE);
      done
    }
  end

  desc "Link a shared database directory"
  task :database do
    run %{
      for FILE in $(ls #{shared_path}/db/*.sqlite3);
      do
        ln -sf #{shared_path}/db/$(basename $FILE) #{release_path}/db/$(basename $FILE);
      done
    }
  end
end


after 'deploy:update_code', 'shared:configuration'
after 'deploy:update_code', 'gems:install'
after 'deploy:update_code', 'shared:database'
after 'deploy:update_code', 'deploy:migrate'

Comments