Using Capistrano with Rails
This article is obsolete, and is preserved here for the sake of those links and bookmarks which already point here. Please see Getting Started: From the Beginning (there’s a link in the sidebar on the right, too) for a more up-to-date how-to for getting your new Rails application to deploy with Capistrano.
Most people using Capistrano to with Rails applications will be doing so to deploy them, and (at least initially) will be deploying them to only a single server. Naturally, as enterprises grow the hardware demands increase as well, but this walk-through will start as small, just as most new ventures should.
Assumptions and Requirements
This tutorial makes the following assumptions about your development and production environments. Please read these through carefully, since they affect the outcome of the tutorial. Be sure to adjust your own usage accordingly if your situation differs from the points outlined below.
- You’re wanting to deploy a Ruby on Rails application, which you’ve already written.
- You’re using Subversion to manage the source code for your application.
- You’ve already got your production environment settled, having decided which web server software and which DBMS you are going to use. If you haven’t decided these things, other tutorials will eventually cover that. For now, there have been several blog articles posted in the past on this subject that I’m sure you could Google for.
- You are deploying to a single server, at least initially.
- Your username is the same for both your subversion repository and your deployment machine.
- Your subversion repository is accessible from both your local host, and the host that you will be deploying to.
- You have configured a public key to use for SSH access to your target host.
- You’ve already created (though perhaps not populated) the database for your application, and set up the user that your application will use to query the database.
Enabling Capistrano
Capfiles
As with tools like Rake and Make, Capistrano relies on special configuration files called “capfiles” to define what it should do and how it should do them. The “cap” utility will look in the current directory for any file named “capfile” or “Capfile”, and will continue looking up the directory tree until it finds one. Then, it will read that file, internalizing any task definitions, role definitions, variable settings, and so forth.
You will sometimes see these “capfiles” referred to as “recipe files”, since they let you define “recipes” (tasks) to use on your servers.
First, you’ll need to create a capfile for your project. Rails’ convention is to put all configuration information under the ‘config’ directory, but Capistrano (like Rake and similar tools) wants its files in the current directory. We make everyone happy by putting a skeleton “Capfile” in the root project directory, which simply loads a file called “config/deploy.rb”. All of your deployment configuration will go in the latter file.
To help get you started, Capistrano comes with a simple script called “capify”, which will stub out those two files for. Simply call it, and pass the location of your project’s root directory. If you are already in that directory, you can simply type:
capify .
You should now be able to get a listing of all of the tasks that are available to you, out of the box, via Capistrano:
cap -T
Most of them are deployment-related, as you would expect. This walk-through won’t mention more than a few of them, but you can read more about any one of the tasks by asking Capistrano for more information, via the “-e” (“explain”) switch:
cap -e deploy:pending:diff
Project Details
Next, you need to tell Capistrano a few bits of information about your project. Open the “config/deploy.rb” script. Initially, it will look something like this:
set :application, "set your application name here"
set :repository, "set your repository location here"
# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
# set :deploy_to, "/var/www/#{application}"
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion
role :app, "your app-server here"
role :web, "your web-server here"
role :db, "your db-server here", :primary => true
Go ahead and change the value for the :application variable to the name of your application, as it might appear as a directory name. Typically, this will be one or two words, with no spaces, all lower-case, but you can do it however you want.
Then, change the value for the :repository variable to be the location of your subversion repository. This typically looks something like this:
set :repository, "http://svn.sourcecode.com/project/trunk"
Note: if you aren’t using subversion, you’ll want to set the :scm variable accordingly, and make sure your repository is formatted correctly for your SCM of choice.
By default Capistrano will try to deploy your application to a directory called /u/apps/#{application} on the remote servers (where #{application} is the value of the :application variable). If that isn’t where you want things deployed on your production environment, be sure and set the :deploy_to variable.
Lastly, set your server as the deployment target for the :app, :web, and :db roles:
set :app, "www.myserver.com" set :web, "www.myserver.com" set :db, "www.myserver.com", :primary => true
Capistrano uses this idea of “roles” to help specialize the behavior of certain tasks regarding certain kinds of machines. When you’re only deploying to a single server, this distinction doesn’t matter so much, but when you’ve got a server farm you’re trying to maintain it comes in very handy! For now, just set the same host for all three roles.
That’s all you need to tell Capistrano, then, at least initially. Let’s move on!
The “spin” Script
The first time you deploy your application, Capistrano is going to try to fire up the “listeners”. These are the FastCGI or Mongrel processes that drive your application.
This is the most involved part of setting your application up for deployment, and it would be complicated whether you were using Capistrano or not. You have a few different options. Some of the most commonly used are:
- Use FastCGI, managed directly by the web server.
- Use FastCGI, managed externally by yourself.
- Use Mongrel, with the web server proxying the requests to your cluster of mongrel processes.
If you don’t already know how you’re going to proceed, you should do some reading on these options. Mongrel is where most people are going these days, so you may want to start reading there, but FastCGI is still pretty widely used, too. This tutorial assumes you already know how you’re going to be running your application.
Server-managed FastCGI
This option may be your only option, if you are on a shared host. In this case, your first deploy will be a bit more complicated than described in this document, but don’t fear! It’s not that bad, and it’s only your first deploy. Subsequent deploys will go more smoothly.
For one thing, you’ll need to add a few tasks to your “config/deploy.rb” file, to help Capistrano know what needs to be done when starting your application:
task :restart_web_server, :roles => :web do # restart your web server here end after "deploy:start", :restart_web_server
The actual method for restarting your web server will depend on what software you’re using, as well as how your host is set up. You may need to invoke “apachectl”, or some rc script, or even some custom script provided to you by your shared host.
Self-managed FastCGI
This option gives you must greater flexibility, and even lets you take advantage of some goodies that Rails provides, out of the box. To let Capistrano start your application with self-managed FastCGI processes, you’ll first need to make sure your web server is configured to look for these “external” FastCGI processes. You should also make sure that the “spawn-fcgi” script is installed on your servers. It is typically installed as part of the Lighttpd server, but it works with any web server, and is used to start a stand-alone FastCGI process.
Once that’s installed, you just need to write a simple “spin” script and put it in the “script” directory of your project. It will just call the “script/process/spawner” utility provided by Rails, to start your application listeners. A sample “script/spin” for a small application might look like this:
/path/current/script/process/spawner fcgi -p 11000 -i 3 -r 5
Be sure and replace the ”/path/” component with the full path to your “deploy_to” location.
The script above will start 3 FastCGI processes, listening on ports 11000, 11001, and 11002, which will be checked every 5 seconds to make sure they are still running.
Mongrel
Mongrel, like external FastCGI processes, requires you to configure your web server such that requests get forwarded to your pool of listeners. (This tutorial won’t tell you how to do that, so be sure and go do some reading if you decide to take this route.) Once you’ve got mongrel all set up on your server, you need to tell Capistrano how to start those processes. There are many different ways to do this, but the simplest is to create a script called “spin” in your “script” directory, as was discussed for the external FastCGI option, above. Your “script/spin” file might look like this:
/path/current/script/process/spawner -p 11000 -i 3
That will start 3 mongrel processes, on ports 11000-11002.
Setup
Time to run your first Capistrano command. At a terminal prompt, type:
cap deploy:setup
Capistrano will log into your server and try to set up a simple directory hierarchy, which will use to support your application’s deployment. Every Capistrano deployment will use this same basic layout, which is:
#{deploy_to}/
#{deploy_to}/releases
#{deploy_to}/shared
#{deploy_to}/shared/log
#{deploy_to}/shared/system
#{deploy_to}/shared/pids
Every time you deploy your application, a new directory is created under the “releases” directory, and then a symlink is created at ”#{deploy_to}/current” that points at the new release. This “current” symlink should be considered the root directory of the currently active release.
Checking dependencies
So, you’ve got the directory tree set up now. Let’s just make sure we’ve got all the software installed that Capistrano thinks we need:
cap -q deploy:check
(The “-q” switch just tells Capistrano to run in “quiet” mode; you can leave that switch off if you want a more verbose description of what it is actually doing.)
The output of that command will either be a line saying you have all necessary dependencies installed, or a list of dependencies that could not be found. For instance, if you don’t have subversion installed on the remote host, that will be mentioned as a missing dependency.
Note: If you do have subversion installed on the target host, and it is still showing up as a missing dependency, then you might have it installed in a non-standard location. In that case, you’ll need to tell Capistrano specifically where the “svn” command is located. Just add the following line somewhere in your “config/deploy.rb” file:
set :scm_command, "/opt/local/bin/svn"
(Obviously, set the value to be the actual path to the “svn” executable for your own environment.)
Once deploy:check reports that all the dependencies are found, you’ve got a good chance of your first deploy actually working! Let’s give it a shot.
The Cold Deploy
The first time you deploy your application is kind of an odd case; usually, when you deploy, your application will already be running, so the deploy simply pushes the code out, updates that “current” symlink, and then restarts your app.
The first time, though, your app is not already running. Things are “cold”. For this case, you can use the “deploy:cold” task:
cap deploy:cold
This task will push the code out to your servers and update the symlink, just like deploy does. However, it will also run any migrations that need to be run (letting you to get your database schema set up) and will then start your application’s listeners. Note that if you haven’t configured your web server and your “spin” script correctly, the cold deploy may fail at that last step; in that case, you’ll have to get your hands dirty by logging into your server and starting up your listeners manually. Once they are running, though, you should be able to access your application via a browser!
Subsequent Deploys
After the first time, things are much simpler:
cap deploy
That will push the new code, symlink it, and then restart your application so that it uses the new code. Be sure to try this a process a few times before announcing your application, just make sure you’ve got all the wrinkles out of it. If things fail, figure out why and tweak accordingly, so that subsequent deploys can be seamless, painless, and smooth.
Rolling back
Sometimes, you push a lemon into production. It happens. Things blow up, people scream at you, and the world generally ends. Don’t let it get you down.
Capistrano makes it easy to roll your application back to the previous release:
cap deploy:rollback
Because Capistrano deploys each new release into it’s own directory, rolling back is painless; it just updates the “current” symlink to point to the previous release and then restarts your application again. Easy!
Next steps
This walk-through only showed you how to set up your application on a single server. As you scale your application upwards, eventually you’ll want to branch out and build up a cluster of servers, some specialized to server your application, others specialized to run the web server, and so forth. Capistrano makes it very, very easy to add new servers to your deployment process.
First, you just tell Capistrano about each server, and what role each plays:
role :app, "app1", "app2", "app3", "app4" role :web, "web1", "web2" role :db, "db1", :primary => true
For most clusters, your individual machines will be behind a firewall, so that you’ll have to access them via some gateway machine. Capistrano makes that easy, too, letting you specify the gateway server, and then tunneling all requests to the other servers through that one:
set :gateway, "my.gateway.com"
Then, set up each new server:
cap deploy:setup
Then, deploy (or deploy:cold) as necessary. Not bad at all!
