Deploying non-rails apps with Capistrano, Mercurial, and Bitbucket

# 14 Mar 2011

Capistrano makes deploying Ruby on Rails applications easy. Having experienced how easy, I was eager to use Capistrano to make deploying non-Rails applications just as easy. I wasn’t able to find comprehensive info on actually making this work from start to finish. Here’s how to do it.

Assumptions

Your version control system of choice is Mercurial, stored at Bitbucket. You want to deploy to a server running Apache. Your development machine is running Mac OS X and you have Capistrano installed.

Capifying Your Project

Capistrano has fairly good documentation for this step, and I don’t see this changing much in the future. Open Terminal.app and run:

cd /path/to/your/project
mkdir config
capify .

Capistrano will create a couple of files for you. The important one is config/deploy.rb. Open it. Then replace its contents with the following:

# User for deployment server
set :user, "your server user here"
set :use_sudo, false # don''t try to use root access

set :application, "your application name here"

# short form instead of the role-based definitions just below
server "your server url here", :app, :web, :db, :primary => true

role :web, "your web-server here"                          # Your HTTP server, Apache/etc
role :app, "your app-server here"                          # This may be the same as your `Web` server
role :db,  "your primary db-server here", :primary => true # This is where Rails migrations will run
# role :db,  "your slave db-server here"

# Deployment will actually be to #{deploy_to}/current, so your document root on your server needs to be set to that also.
set :deploy_to, "/path/to/www/directory"

set :repository,  "ssh://hg@bitbucket.org/bitbucket_username/project"

set :scm, :mercurial
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`

### CONFIGURATION ABOVE -- DO NOT EDIT LIGHTLY BELOW THIS LINE ###

# Overriding some tasks in the ''deploy'' namespace since this isn''t a rails app. This way, you can still use ''cap deploy'' to deploy this app.
namespace :deploy do
  task :start do ; end
  task :stop do ; end
  task :restart do
    run "ln -nfs #{release_path} #{current_path}"
  end
end
# Or, use this as a backup if overriding the deploy tasks above does not work for some reason. Then, deploy with ''cap deploy_nonrails''.
# task :deploy_nonrails, :roles => :app do
#  run "hg clone #{repository} #{release_path}"
#  run "ln -nfs #{release_path} #{current_path}"
#  run "ln -nfs #{shared_path}/uploaded #{current_path}/uploaded"
# end

Now, update deploy.rb with your specific information. You have been Capify’d!

Bitbucket Authentication

You will notice that in deploy.rb, we have only told Capistrano about Bitbucket via the repository parameter, and that we are using a URL that begins with SSH. This means that authentication with the Bitbucket server will be via SSH, which will require that we have a public-private key pair. We will set that up now.

Bitbucket has a helpful page which covers how to access your Bitbucket repository via SSH. The important part of it for this discussion is to set up your public key with Bitbucket.

If you don’t have a public-private key pair, follow that guide to set one up. In Terminal.app, run:

ssh-keygen

And follow the prompts. Make sure to note the location of your public key so that you can get to it later. It is probably at ~/.ssh/id_rsa.pub or ~/.ssh/id_dsa.pub.

Now, you’ll need to give Bitbucket your public key (ends in .pub). Look in your Bitbucket Accounts page to find where to do that.

Also, update your local repository’s parent by updating .hg/hgrc in your repository’s root with:

[paths]
default = ssh://hg@bitbucket.org/bitbucket_username/project

You should be able to connect to Bitbucket without typing a password.

Deployment Server Setup

Just copy your public key into ~/.ssh/authorized_keys on your deployment server. Assuming that you don’t already have any public keys set up already then run:

scp ~/.ssh/id_rsa.pub user@server:~/.ssh/authorized_keys

You should now be able to authenticate with your server without typing a password.

You’ll also want to change your Apache HTTPD document root to point to the current alias that Capistrano will create in your server’s www root. Different web hosts have different ways of allowing you to do this. Mine provides a web interface that can adjust this setting. Check yours.

SSH Key Forwarding

This was, for me, the trickiest part. What Capistrano is going to do when you deploy your application is connect to your deployment server (authenticating using your private key on your development machine and your public key in ~/.ssh/authorized_keys on your deployment server), and then, from your deployment server, connect to your Bitbucket server to access your repository.

In order for this to work, SSH Agent Forwarding must be enabled on your development machine. Add this to ~/.ssh/config, creating the file if it doesn’t already exist:

Host *
ForwardAgent yes

Running Capistrano

Open up Terminal.app, navigate to your project’s root directory, and run:

cap deploy

The most recent version of your application in Bitbucket should now be deployed to your server.