Capistrano

Capistrano is used for “automating tasks via SSH on remote servers, like software installation, application deployment, configuration management, ad hoc server monitoring, and more.” It is written in ruby and is commonly used to deploy Rails applications. Capistrano can be used to deploy applications written on any language. It runs commands on remote servers via SSH so it’s not specific to any language.

I will show you how to use capistrano for deploying a Rails application. The goal is to deploy an application by running one command – “cap deploy”. This should update your code from Subversion, and restart your server.

I assume that you have a rails setup on your server. I use the nginx web server, mongrels and mongrel_cluster.

To install capistrano

gem install capistrano

To start using capistrano on your Rails application,

cd RAILS_ROOT
capify .

You should see two files – Capfile and config/deploy.rb. Capistrano looks for Capfile when you run any capistrano commands. The default Capfile loads config/deploy.rb. deploy.rb contains the settings for your application.

We will deploy the Rails app “Hello Labs”. This can be found on our repository. Let’s edit deploy.rb.

Set the user and runner that will run the commands on your server.

set :user, "crigor"
set :runner, "crigor"

Set the application name

set :application, "hellolabs"

Set the scm and repository

set :scm, :subversion
set :repository, "http://labs.svn.admoolabs.com/hellolabs/trunk"

The default :scm is actually :subversion but I like to put it anyway.

Set the directory on the target server where you will deploy the application.

set :deploy_to, "/var/www/#{application}"

application is “hellolabs” which you set earlier. The deploy_to directory, which I’ll call DEPLOY_ROOT, is /var/www/hellolabs. You should create this directory on the target server. On Ubuntu, I set the group to www-data so mongrel has access to it.

Set the servers.

role :app, 'hello.labs.admoolabs.com'
role :web, 'hello.labs.admoolabs.com'
role :db, 'hello.labs.admoolabs.com', :primary => true

You can also use the IP address instead of the domain.

If nginx, mongrel, and mysql are all on the same server, put the same domain or IP address.

Now we will run our first capistrano task. Make sure /var/www/hellolabs exists on your server. On the RAILS_ROOT, run

cap deploy:setup

This will create the releases directory and shared directory under the hellolabs directory on the remote server. If you get a permission error, make sure the user you specified has access to /var/www/hellolabs.

Capistrano will ask for you server password. If you don’t want to enter your password every time you run a capistrano task, you can add

set :password, "mypassword"

Check if we have met the dependencies.

cap deploy:check

The output, if deploy:check is successful, looks like this.

Before we deploy the app, we define the deploy:restart task. By default capistrano runs /var/www/hellolabs/current/script/process/reaper. I use mongrel and mongrel_cluster so let’s add

namespace :deploy do
  desc "Restart the mongrels"
  task :restart do
    run "mongrel_rails cluster::restart -C #{shared_path}/config/mongrel_cluster.yml"
  end
end

Create the /var/www/hellolabs/shared/config directory and add mongrel_cluster.yml. We also need to add database.yml. I don’t commit database.yml in my repository since it contains the database password.

We have to symlink mongrel_cluster.yml and database.yml every time we deploy.

after "deploy:update_code", "deploy:symlink_configs"
namespace :deploy do
  desc "Symlink the config files."
  task :symlink_configs do
    run "ln -nfs #{shared_path}/config/database.yml #{latest_release}/config/database.yml"
    run "ln -nfs #{shared_path}/config/mongrel_cluster.yml #{latest_release}/config/mongrel_cluster.yml"
  end
end

We’re now ready to deploy our application.

cap deploy

If you see something similar to this, your app has been deployed.

The releases directory will contain directories with the timestamp as the name like 20081017125102 and 20081017132929. These directories will contain the rails application.

Below, you can see that current is a symlink to 20081017132929. /var/www/hellolabs/current is your RAILS_ROOT.

cap_directory_structure.jpg

Check the URL of your app. http://hello.labs.admoolabs.com

If you need a username and password to checkout your repostory, add

set :scm_username, "username"
set :scm_password, "password"

To get the list of capistrano tasks available, run cap -T.

For more information, check the capistrano website.

Here is the complete deploy.rb

set :user, "crigor"
set :runner, "crigor"

set :application, "hellolabs"
set :scm, :subversion
set :repository, "http://labs.svn.admoolabs.com/hellolabs/trunk"
set :deploy_to, "/var/www/#{application}"

role :app, 'hello.labs.admoolabs.com'
role :web, 'hello.labs.admoolabs.com'
role :db, 'hello.labs.admoolabs.com', :primary => true

after "deploy:update_code", "deploy:symlink_configs"
namespace :deploy do
  desc "Symlink the config files."
  task :symlink_configs do
    run "ln -nfs #{shared_path}/config/database.yml #{latest_release}/config/database.yml"
    run "ln -nfs #{shared_path}/config/mongrel_cluster.yml #{latest_release}/config/mongrel_cluster.yml"
  end

  desc "Restart the mongrels"
  task :restart do
    run "mongrel_rails cluster::restart -C #{shared_path}/config/mongrel_cluster.yml"
  end
end