Deployment with Capistrano
Capistrano is most often used for deployment of Rails application. It uses a simple DSL similar to Rake that allows you to define roles to machines and any additional tasks that need to run during deployment.
Here I will walk you through a Capistrano deploy for a simple Rails application residing in your local machine to a single web server. I am assuming this is a simple Rails app that runs on just Webrick even though it is never advisable to do the same for a production setup.
Installing Capistrano
If you are using a Gemfile, you can just add the gems below and do a bundle install. Else install the gems manually from the command line.
gem install capistrano
gem install capistrano-ext
Capistrano assumes that you have SSH access to the server you are deploying to. If you do not then Capistrano is not going to work for you.
Getting setup with Capistrano
Navigate to the root of yours Rails app and ‘capify’ it.
capify .
This will create a file called Capfile(like Rakefile) in your project root. In addition it will also create a deploy.rb in your config folder.
Working with Capistrano
In the deploy.rb, you can begin setting up your application for deploy
set :application, "deploy_demo"
Capistrano comes with a number of recipes to connect to different repos, like Git, SVN and Perforce. However the setup for synch up different repositories is a bit more involved. Here, I am assuming that you are using one of these version control systems and your local rails app has been updated to a state fit for deploy, and all you need to do is copy the application over to the remote server.
So lets go ahead and set the source control to none and deploy mechanism to copy.
set :scm, :none
set :deploy_via, :copy
Specify the user name and password for ssh access and the path to deploy to on the remote server. Also set the use_sudo to false, if you do not want to deploy the application as root.
set :user, "username"
set :password, "password"
set :deploy_to, "/home/user/apps"
set :use_sudo, false
While we are going to deploy to a single box, we can the ability to deploy to multiple environments. This is where the capistrano-ext gem is going to come handy.
Include multistage at the top of the deploy.rb file
require 'capistrano/ext/mulitstage'
And while you are there add a couple of other includes for rvmrc and Bundler support as well.
require 'rvm/capistrano'
require 'bundler/capistrano'
Now specify your environments or stages. For me its just going to be qa for now. I have also set the default environment to qa.
set :stages, %w(qa)
set :default_stage, "qa"
This does it as far as deploy.rb goes. We still need to add a config file for qa stage. This is done in a qa.rb file inside the config/deploy folder.
In this config file, specify the different roles and set the repository to the current project root.
role :web, "server"
role :app, "server"
role :db, "server", primary: true
set :repository, "."
Rubber hits the road
Capistrano needs to create an initial directory structure for deployments. This is done as a one time task from the project root
cap qa deploy:setup
or
cap deploy:setup
Once this is done, let Capistrano run checks to verify it has everything it needs
cap deploy:check
If you do not see any errors, then you can try out the deploy. For a first time deploy, it is suggested to go with
cap deploy:cold
For subsequent deploys you can just do
cap deploy
Additional Configurations
- If you want your assets copied over as well, load these 2 recipes in the deploy.rb
load 'deploy'
load 'deploy/assets'
- If RVM is throwing a ‘No value for $TERM and no -T specified’ error add this environment variable to your Capfile
default_environment["TERM"] = "xterm"
- If Capistrano complains about a missing Rake gem and you know it should be present, add these settings to your deploy file
set :rvm_ruby_string, "local"
set :rvm_type, :user
- If you are deploying via a proxy then this needs to be set in your Capfile
default_environment["http_proxy"] = 'http proxy:80'
default_environment["https_proxy"] = 'https proxy:80'
- Adding deploy hooks to stop, start a server
Capistrano provides hooks that you can define as tasks within the deploy.rb file that will restart a web server or run other custom scripts. For our simple Rails app that uses Webrick we can do something like this
pid_file = "/home/#{user}/apps/#{application}/tmp/pids/server.pid"
namespace :deploy do
task :start do
run "cd apps/#{application}/current; rails s -e test"
end
task :stop do
run "kill -s QUIT `cat #{pid_file}`" if File.exists?(pid_file)
end
task :restart do
stop
sleep 2
start
end
end
- If you see errors complaining about rvm-shell not found, add this to your deploy.rb
set :default_shell, "/bin/bash -l"
- If you notice error relating to gnutar being not available you can switch to using zip compression which should be available by default on *nix systems.
set :copy_compression, :zip