Automate Rails Application Deployment with Capistrano
by Saurabh Bhatia
May 7, 2010
When you're ready to deploy your Ruby on Rails application, Capistrano can make the process much easier.
Capistrano, a deployment tool that helps to automate Rails application deployment, harnesses the power of metaprogramming to allow the user to define the values of deployment techniques, repositories, databases and exception notifications. In this article, I explain how to automate your Rails application deployment using Capistrano, Git (as the repository), and Phusion Passenger (as the server). I will use the demo Rails application from my previous article on Phusion Passenger.
How It Works
As in my previous tutorial, the Rails application to be deployed resides inside the /var/www directory. At regular intervals, Capistrano will work as follows:
Run using cron.
Go to the Git repository.
Copy the source code to the specified folder (/var/www).
Restart Apache2, loading the Passenger module.
It will also run the required migrations and modifications on the database, applying the domain name for the application. Capistrano does all this using SSH, a secure channel for carrying out this activity (see Figure 1 below). This means that the repository can reside in a remote location and applications can be deployed to another server.
Capistrano supports both Subversion and Git, but Git is becoming increasingly popular with Rails developers and actually replacing Subversion in a lot of places -- especially with GitHub making repository hosting so easy.
So, let's install Capistrano, Git, and Phusion Passenger:
Capistrano configuration is written in a file called deploy.rb, which sits in the config folder of the Rails application. This file contains various sections for configuring the source control system, the database, the server details and the DNS information.
Now, set up SSH public key access between the systems. This ensures that the channel is safe and is accessed by the right people.
The Repository Setup
Subversion is the default repository of Capistrano, so we need to go to deploy.rb and change it to our taste. The contents of deploy.rb should look like this:
set :scm, :git
set :application, "EmployeeInformationManager"
set :repository, "git@safewlabs.com:eim-app.git"
set :branch, "master"
#set :scm_username, 'appman'
#set :runner, 'appman'
#set :use_sudo, false
set :deploy_via, :copy
In the section of the file shown above, :application and :repository define the name of the application and the direct link to the repository. As a Git repository contains various branches, we need to define which branch to access in order to get the latest working copy of the code for deployment.
The :deploy_via command defines the deployment strategy. There are four kinds of deployment strategies:
Copy allows people behind the firewall, which does not allow them to access their SCM over the network. The Copy strategy has some variables of its own. It checks the code out from the repository and creates a local copy of the version inside the directory to be deployed. It typically looks like this: /var/www/eim-app/releases/20101004215259/.
Remote_cache enables speedier deployment because it places a working copy of the code in the cache of the server where it is supposed to deploy the application. It uses the cache function of the repository, matches the name of the deployment directory and the repository, and then deploys it.
Export is a Subversion-specific command. It extracts a copy of the code from the HEAD. The exported repository cannot be updated via svn.
Checkout also is a Subversion-specific command. It's used to perform a typical Subversion checkout inside the deployment directory.
Passenger Setup
The deploy to command defines the absolute path of deployment for the application.
set :deploy_to, "/var/www/#{application}"
The only thing that we need to define for Passenger is a way to restart the Apache server and restart the application when the changes are applied. This is because, like Mongrel, Apache does not identify the changes in the application out of the box and needs to load it in order for those changes to take effect.
Passenger (aka mod_rails) uses a simple method to restart. It needs us to create a simple file named restart.txt in the tmp directory of Rails. As soon as Passenger reads that file, the application restart takes effect; run "touch #{current_release}/tmp/restart.txt" does this for us. So, the deploy.rb looks like this:
namespace :deploy do
task :start, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
task :stop, :roles => :app do
# Do nothing.
end
desc "Restart Application"
task :restart, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
end
Automating All This
Cron helps us to schedule the process of running Capistrano. We can simply define our Capistrano command in the cron edit and make it run every Friday at 18:30 hours.
saurabh@saurabh-laptop:~$ crontab -e
# m h dom mon dow command
30 18 * * 5 cap:deploy
The only thing we must do before completing this process is to assign the correct permissions to the server directory.
So, after we have written these directives, let's see what our deploy.rb looks like:
set :application, "EmployeeInformationManager"
set :repository, "git@safewlabs.com:eim-app.git"
set :deploy_to, "/var/www/symbid-app-23-jan/#{application}"
set :scm, :git
#set :scm_username, 'appman'
#set :runner, 'appman'
#set :use_sudo, false
#set :branch, "master"
set :deploy_via, :copy
role :app, "myapp.com"
role :web, "myapp.com"
role :db, "app_production", :primary => true
namespace :deploy do
task :start, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
task :stop, :roles => :app do
# Do nothing.
end
desc "Restart Application"
task :restart, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
end
Other Automations
The example we have gone through here makes deployment easier. However, you can simplify many other Rails tasks like migrations, database creation, and continuous integration with automated builds and failure notices.
About the Author
Saurabh Bhatia has been working with Rails since early 2006 and has a startup company, Safew Labs, that offers Rails consulting. He likes to write clean code, read and write.