Deploying With Capistrano Without Rails
By Ryan Florence, published 2010-07-27
Part of the issue Git Your Act and Deployment Together.
Developing web apps with Ruby on Rails has a lot of conveniences developers are almost smug about. Capistrano, though not a part of rails directly, I think belongs in the category. After using it once I was sold. What is it? Straight from capify.org:
Simply put, Capistrano is a tool for automating tasks on one or more remote servers. It executes commands in parallel on all targeted machines, and provides a mechanism for rolling back changes across multiple machines. It is ideal for anyone doing any kind of system administration, either professionally or incidentally.
Capistrano runs on your workstation, not the server, and is arguably the best deployment program out there. However, it’s completely smitten by Rails. Enter railsless-deploy, a gem by Lee Hambley. From the gem’s README:
If you want to get the most out of Capistrano and you do not want to have to deal with the railsisms that ship by default, this is the gem for you.
We’re going to see just how easy, and awesome, capistrano and railsless-deploy are together for any website. This is a very quick how-to, getting you over the hump with Capistrano. For more in depth resources, check out the links at the end of this article.
What you will need
Some of this is from capify.org
- Ruby
- SSH access to a server with a POSIX-compatible shell installed
- Access to your server with a public key
This is the setup I’m on:
- Workstation: Mac OS X 10.6, Ruby 1.8.7, git
- Server: Linode, Ubuntu Hardy VPS
Installation
Many capistrano investigators think it’s a server-side program. It’s actually installed on your workstation, not the server. Like all gems, open the terminal and install them:
$ gem install capistrano
$ gem install railsless-deploy
Create and configure the test website
Here are a few commands to make a silly test site.
$ mkdir test
$ cd test
$ echo "Hi and stuff" > index.html
Capistrano requires your site to be a repository of some sort, I’m going to use git.
$ git init
Capify your site
Hopefully none of that was frightening. Now the Capistrano stuff shows up. First you “capify” your site with a simple capify
and then a path.
$ capify .
This will create a few files for you: Capfile
, config/
, config/deploy.rb
. Now we do some of the railsless-deploy stuff. Open up the Capfile and change it to:
require 'rubygems'
require 'railsless-deploy'
load 'config/deploy.rb' if respond_to?(:namespace)
The Capfile does little more than tell capistrano where the deployment “recipe” is. Open up the recipe in config/deploy.rb
and paste this into it, replacing my stuff like “example.com” with your own information, of course:
# replace these with your server's information
set :domain, "example.com"
set :user, "user"
# name this the same thing as the directory on your server
set :application, "test"
# use your local repository as the source
set :repository, "file://#{File.expand_path('.')}"
# or use a hosted repository
#set :repository, "ssh://user@example.com/~/git/test.git"
server "#{domain}", :app, :web, :db, :primary => true
set :deploy_via, :copy
set :copy_exclude, [".git", ".DS_Store"]
set :scm, :git
set :branch, "master"
# set this path to be correct on yoru server
set :deploy_to, "/home/#{user}/public_html/#{application}"
set :use_sudo, false
set :keep_releases, 2
set :git_shallow_clone, 1
ssh_options[:paranoid] = false
# this tells capistrano what to do when you deploy
namespace :deploy do
desc <<-DESC
A macro-task that updates the code and fixes the symlink.
DESC
task :default do
transaction do
update_code
symlink
end
end
task :update_code, :except => { :no_release => true } do
on_rollback { run "rm -rf #{release_path}; true" }
strategy.deploy!
end
task :after_deploy do
cleanup
end
end
Now go ahead and commit everything to git
$ git add .
$ git commit -m 'first commit'
Setup the server and deploy
Before we go any further with Capistrano there are a couple things that need to happen on the server. First, you need a directory for the site to be deployed to. In deploy.rb
you specified a path for deploy_to
. Make sure that exists:
$ ssh user@example.com
$ mkdir /home/user/public_html/test
Now go back to your workstation. Capistrano sets up the server for you. Run this command:
$ cap deploy:setup
It’s going to run several tasks on the server. If you’ve still got the server shell open, list the directory of your site and you’ll see:
test/
releases/
shared/
Now we are ready to deploy:
$ cap deploy
Once that finishes, go again to your server shell and list the directory. You’ll see something like:
test/
current/
releases/
shared/
I said earlier there were a couple things to do on the server. This is the second, you need to point your webserver document root to the current
directory. In my example, using apache, I’d set it to /home/user/public_html/test/current
. Of course, if your web root is a sub folder of your repo then you’d do ../current/public
or whatever.
Congratulations! You’ve now deployed the site.
Deploying the next version
On your workstation, make some changes to index.html
, commit the changes to git, and then run the deploy command again.
$ echo "I am new text" > index.html
$ git commit -a -m 'updated stuff'
$ cap deploy
How easy was that? Now get on the server and check out the releases
directory, it’ll look something like
$ ls releases
20100727171750 20100727172413
In your deploy.rb
you can specify how many releases to keep around. This is handy because you may need to rollback if you release a steaming pile on accident.
Rolling back a release
$ cap deploy:rollback
This will go on the server, point the current symlink to the release before last and remove the last release completely. Headaches and major disasters averted.
Now what?
For most sites, this is enough. But for other sites, like a django app or a wordpress install, you may want to run some other tasks on the server. Here are a few links I think are good. If you know of some other resources, comment and I’ll add them: