Github-style capistrano deployments

Aug 26, 2010

If you've deployed a rails app the chances are high that you've done it using capistrano. Capistrano has come a long way, but it was originally designed back when we were all using svn to manage our code. Times have changed, and we can make some significant improvements to the default process.

Credit where credit is due

First, I can't take the credit for this refactor of the capistrano deployment scripts. That honour goes to Chris @ GitHub, and he has a great explanation of what he did and why over on their blog.

I've been using this style of deployment on all my projects since Chris announced it, but there are some things I needed which were supported by either capistrano natively or by these new additions.

Setting up your web server configuration

I almost always deploy to an nginx server running passenger, apache is a rarity these days. In any event I've made an assumption that both servers will be setup to dynamically include their virtual host config files from a specific location. As a result, running cap deploy:setup will not also create the appropriate config file for your server and restart apache/nginx. You can set the nginx_conf_dir or apache_conf_dir to specify the appropriate place to put the file. Take a look at config/deploy/apache.rb and config/deploy/nginx.rb for the respective configuration templates.

Moving all application settings to a common place

Common application settings have all been moved to config/deploy/settings.rb, so this will include things like your application name, source control system (this approach only supports git) and repository location. You'll need to change things in this file to be relevant to your own application.

Deploying to different target environments

I'll usually have more than one environment I want to deploy the code to (production, staging, demo, etc.), and cap has a built in means of handling this… you don't need to go install some extra gem or plugin. Each target is defined in config/deploy/targets.rb, and example of definition is as following:

task :production do
  role :web, ["192.168.1.10", "192.168.1.11"]
  role :app, ["192.168.1.10", "192.168.1.11"]
  role :db,  "192.168.1.12", :primary => true
  set :web_server, :nginx
  set :web_port, "80"
end

This file is for any settings that will vary from machine-to-machine or between environments. Anything that is going to be the same on every machine belongs in config/deploy/settings.rb

How to get started

Go take a look at Git-based-deploy GitHub repository, grab the code and get deploying. Submit me any patches if you find problems or think of something worth including.

This post was originally published at Ruby Pond

Hi, I'm Glenn! 👋 I've spent most of my career working with or at startups. I'm currently the Director of Product @ Ockam where I'm helping developers build applications and systems that are secure-by-design. It's time we started securely connecting apps, not networks.

Previously I led the Terraform product team @ HashiCorp, where we launched Terraform Cloud and set the stage for a successful IPO. Prior to that I was part of the Startup Team @ AWS, and earlier still an early employee @ Heroku. I've also invested in a couple of dozen early stage startups.