Using Capistrano to deploy Rails apps from Gitolite

2012-08-23 17:29:25 -0400

Here, I'll show you how to deploy a Rails app from a Gitolite repository via Capistrano. In this example, I'm running a Phusion Passenger on NGINX on Ubuntu 10.04. The instructions should be very similar for Ubuntu 12.04.

First, understand what we're doing here. I'm assuming you are using Gitolite for version control (although similar instructions would probably work for Github). We're going to add a read-only deployment key to the Gitolite repository. When you run cap deploy</code>, Capistrano will log into your production server via SSH (using public key authentication). Then the Capistrano script will instruct the production server to check out the latest version of your app from the Gitolite repository into a directory on the production server. Finally, the Capistrano script will change a symlink to the new version of your app and instruction Phusion Passenger to reload the app into memory on the next hit.

Setting up your production server</h2>
Create a new user for deployment-related tasks on your production server. Switch to that user.

sudo adduser deployuser
sudo su - deployuser</pre>
Now, generate some SSH keys for that user. Run as the deployuser:

ssh-keygen -t rsa</pre>
I don't typically enter a password for this keypair. The reason is that this keypair is only used for read-only access to your code repository in Gitolite. If your code is highly sensitive, you might want a password. If you enter one here, you will be prompted for it each time you deploy code.

Now, wherever you have your Gitolite admin repository checked out, open it up and add the public key to your keydir folder. I like to keep my deployment keys in a subfolder called something like "deployment".

Say, for example, your Gitolite admin repository is at ~/repos/gitolite-admin</code>. Switch to that path. Now enter the folder keydir</code>. Make a new subfolder called deployment</code>, and then a new file in that folder called something like MyDeploymentKey.pub</code>. Open that file in your editor and paste the public key that you just created from your deployment server. Typically, that key is found at ~/.ssh/id_rsa.pub</code>.

Now, open your gitolite.conf</code> file (in the conf</code> folder in your Gitolite repository). Find your project and add a directive to grant your deployment key read-only access. Here's an example project section:

repo     my-project
RW = JoeCoder
R = MyDeploymentKey</pre>
Note that even though the deployment key could be in a subfolder, you still just enter the filename minus the ".pub".

Save the Gitolite files, commit and push to your Gitolite server.

Setting up Capistrano</h2>
Now, open up your Rails project you want to deploy. Add these gems:

# Gems for deployment
group :development do
gem "capistrano"
gem 'rvm-capistrano'
end</pre>
Run bundle install</code> and then from the top directory of your project, run capify .</code>. This adds Capistrano to your project. Open up config/deploy.rd</code> and add something like this:

require "bundler/capistrano"
require "rvm/capistrano"

set :application, "myapp"
set :domain, "mydomain.com"
set :repository, "git@mygitoliteserver.com:mygitrepo"
set :use_sudo, false
set :deploy_to, "/srv/mydomain.com/public/#{application}"
set :scm, "git"
set :user, "deployuser"

role :app, domain
role :web, domain
role :db, domain, :primary => true

# Add RVM's lib directory to the load path.
set :rvm_ruby_string, 'ruby-1.9.3-p358'
set :rvm_type, :system

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</pre>
This deploy script will checkout your code from the project myproject on mygitoliteserver.com and deploy it to /srv/mydomain.com/public</code> on your production server (make sure you create this directory). Whenever you deploy, Capistrano will touch tmp/restart.txt</code> so that Phusion Passenger restarts with the new code.

Once you are finished editing this script, commit your changes, push your latest code to your Gitolite server.

Deciding who gets to deploy</h2>
For each user you want to allow to deploy code, have them generate a SSH key. On your deployment server, open or create ~deployuser/.ssh/authorized_keys</code>. For each user you want to allow to deploy, add their public key (one key per line) to this file.

Deploying!</h2>
Now, to test out deployment, run from your Rails root on your development machine (the machine that has the SSH key you added to ~deployuser/.ssh/authorized_keys</code>), run cap deploy</code>.