breaking into the unknown…

rails deployment with rvm and capistrano

Leave a comment

In my last post I have explained deploying rails with mina.  This time we will do it with Capistrano. If this post not solved your problem you can get more detail on Capistrano deployment here. For advance learning you can look at Capistrano wiki here. Anyway, we will proceed through the below step

STEP 1: Understanding You server

A server is just like any other machine with restricted access, always up with more resources like RAM, hard disk etc. I will deploy to my friend kapil system as my target server. This machine is running on ubuntu 12.04.

So, our server has below details
username: kapil
password: xyz4154
system name : kapil-handa # it  basically represent the ip

Before moving to next step make below checklist on your server:

  1. You should able to ssh to server i,e kapil@ from your terminal.   see how to ssh to remote machine here
  2. Capistrano deploy your code from SVN or GIT. whatever, Your source repository may be , it should be accessible from your Server . for GIT it is explained here
  3. If you are using RVM on server. create a gemset say myapp to be used by our deployed code. We can automate it by writing few line of code in deploy.rb in step 4. But since it is one time process, better to create it manually on server. managing RVM is explained in this post. Installing ruby and gemset is explained here. Also, I am assuming that you are using RVM > 1.11.0. If you are using some other version of RVM, you better refer this document on rvm configuration with Capistrano
  4. Create a database on which you will run your migration after deployment. It is also one time process, so do it manually on the server running your database. here, we have single server(kapil machine) for everything, so create it here itself.

STEP 2: Installing Capistrano on Your machine

You can install and configure Capistrano with below lines.

-> install gem and run the bundle

Add below lines to the gem file

gem ‘capistrano’
gem ‘rvm-capistrano’ #this is required if you are using RVM on server.

$ bundle install # at project root on terminal

-> generate the default files

$ capify . # this will add two file Capfile and deploy.rb for you as you can see below
[add] writing ‘./Capfile’
[add] writing ‘./config/deploy.rb’
[done] capified!

-> take a look at the capfile, not much to change there.

The ./Capfile has below content
load ‘deploy’ # it will load all default Capistrano task for you, never remove this line unless you do not want to use the default but create your own recepie
load ‘deploy/assets’ # remove this line if you are not using Rails’ asset pipeline
load ‘config/deploy’ # This will load your configuration settings. you add all your setting and script to this file.

-> we familiar with deploy.rb file

This file will contain our deployment script.By default, it have some content, which is more of guiding instruction for you. We will change all of them as per our need. on safer side backup the default file for future reference by renaming it as deploy_backup.rb and create new deploy.rb file. We will write our deployment script to this file.

-> Checkout the  Capistrano Default Methods

Capistrano provides a no of methods which you can use for deployment. You can see the list of method provided by Capistrano with below command

$ cap -vT #it will list all the available methods with sort description as below
cap deploy # Deploys your project.
cap deploy:assets:clean # Run the asset clean rake task.
cap deploy:assets:precompile # Run the asset precompilation rake task.
cap deploy:assets:symlink # [internal] This task will set up a symlink to …
cap deploy:check # Test deployment dependencies.
cap deploy:cleanup # Clean up old releases.
cap deploy:cold # Deploys and starts a `cold’ application.
cap deploy:create_symlink # Updates the symlink to the most recently deplo…
cap deploy:finalize_update # [internal] Touches up the released code.
cap deploy:migrate # Run the migrate rake task.
cap deploy:migrations # Deploy and run pending migrations.
cap deploy:pending # Displays the commits since your last deploy.
cap deploy:pending:diff # Displays the `diff’ since your last deploy.
cap deploy:restart # Blank task exists as a hook into which to inst…
cap deploy:rollback # Rolls back to a previous version and restarts.
cap deploy:rollback:cleanup # [internal] Removes the most recently deployed …
cap deploy:rollback:code # Rolls back to the previously deployed version.
cap deploy:rollback:revision # [internal] Points the current symlink at the p…
cap deploy:setup # Prepares one or more servers for deployment.
cap deploy:start # Blank task exists as a hook into which to inst…
cap deploy:stop # Blank task exists as a hook into which to inst…
cap deploy:symlink # Deprecated API.
cap deploy:update # Copies your project and updates the symlink.
cap deploy:update_code # Copies your project to the remote servers.
cap deploy:upload # Copy files to the currently deployed version.
cap deploy:web:disable # Present a maintenance page to visitors.
cap deploy:web:enable # Makes the application web-accessible again.
cap invoke # Invoke a single command on the remote servers.
cap shell # Begin an interactive Capistrano session.

NOTE : once, you have written the basic required configuration as described in next step, you can use any of the above command to manage your deployment

STEP 4: writing deployment script

set :scm, :git #repository you are using, git is default, so if you are using git, this line is not needed
set :repository, ‘’ #Your repository url
set :application, “” # name of your application
set :deploy_to, “/var/www/” # path where your code will be deployed
set :use_sudo, false  # If you do not mention it as false, Capistrano will try to execute command as sudo user  and will throw error like no tty present and no askpass program specified. basically you will need  the default true, when you do not have root access to server and want to run command as sudo user. In that case, You need to do some extra configuration, which is not covered in this post. Generally, you always have root access to server so don’t worry much

#for us all three role are running on same machine so having same value
role :web, “kapil@” # this is where your web server software runs i,e apache, nginx etc
role :app, “kapil@” # this is where your application layer runs i,e webrick, passenger, mongrel etc
role :db, “kapil@” , :primary => true  # this where your database server run i,e mysql, sql oracle etc

NOTE: These are the essential configuration you need to set for capistrano to work. There are other variable also which you can use as per you specific need. for example,if  you do not want to access the git repository through deploy key setting as described here,but through username password you can set below variables.

set :scm_username, “” # this should be username of admin of repository
set :scm_password, “happyarun8765” #this should be password of admin of repository

The complete list of all the variable is available here

So, we are done with the most basic configuration. let us see what we can achieve with this and how we can improve it in next steps

STEP 5: Setup the folder structure on server

Now, with basic deployment script written in step 4, you are ready to see the power of Capistrano in managing your deployment. first we make the directory below command on the terminal
$ cap deploy:setup

After completion of this command , if you go to your server and look at deploy_to path you have set
in step 4 (/var/www/ you will find below folder structure.

-> /current # it is symlinked folder, which point to most recent folder in releases directory
-> /releases # whenever you deploy your code, it create a new folder with value of date and time when it is deployed,
say if you deployed on 6 dec 2012 at 4.30 folder name will be 201212060430. Then current folder link will be
changed to point to this directory
-> /shared # this folder will contain shared data which remain consistent. for example you can put your
database.yml file in this folder. generally, people do not commit database.yml file to git as it will expose the detail
to outside people. the good practice is to create database.yml file on server manually and later on through
deployment scrip symlink config/database.yml file to the database.yml file in the shared folder.
->/shared/log # it will contain the log information
->/shared/pids # it will contain process ids of running process say nginx, ruby etc
->/shared/system # you can put system related information here

NOTE: If you have not committed your database.yml file to git due to security reason. After running setup you must
create database.yml file with all required configuration in shared folder.

STEP 6: Deploy the code
run below command on the terminal
$ cap deploy

If you have fulfilled the checklist in step 1. The above command will complete successfully. If you login to
server you can find the current git code in /var/www/mayapp/current folder. So are we ready to start the server ??
NO…because , we have not did below step on server which we used to do in development

-> rvm use ruby-1.9.3-p194 # assuming ruby-1.9.3-p194 is used by you
-> rvm gemset use myapp #assuming myapp is gemset you are using for this project
-> bundle install # assuming you have added some new gem to gemfile
-> rake db:migrate # assuming you have added some new migration which need to be migrated

So now, we will modify our deployment script in step 4 to take care of these thing.
Also, I am assuming that database.yml is not commited to git due to security reason, so when Capistrano clone your git
repository in /var/www/myapp/current the /config/database.yml is not there(don’t worry even if it is there), we will generate a symlink of this to /shared/database.yml file

modifying deployment script

require "rvm/capistrano" #This will add more method to cap list under rvm namespace. 
You can see them as usual by typing cap -vT on terminal

set :rvm_ruby_string, 'ruby-1.9.3-p194@myapp' # the name here is important.
here 'ruby-1.9.3-p194@myapp' means you want to use ruby ruby-1.9.3-p194 and 
gemset myapp. this line is must and responsible for configuring rvm with 
Capistrano on server
set :rvm_type, :system # if RVM is installed on server as non root user use
:user instead of :system

set :scm, :git
set :repository, ''
set :application, ""
set :deploy_to, "/var/www/"
set :use_sudo, false

role :web, "kapil@"
role :app, "kapil@"
role :db, "kapil@" , :primary => true

namespace :deploy do

  desc 'Re-establish database.yml'
  task :set_database_symlink do
    run "rm -fr #{current_path}/config/database.yml && cd #{current_path}/config &&
        ln -nfs #{shared_path}/database.yml database.yml" 

  desc 'run bundle install'
  task :install_bundle do
    run "cd #{current_path} && bundle install"

  desc 'run the migration'
  task :migrate do
    run "cd #{current_path} && bundle exec rake db:migrate RAILS_ENV=staging --trace"


before "deploy:setup", "rvm:install_ruby"
before "deploy:migrate", "deploy:set_database_symlink"
before "deploy:migrate", "deploy:install_bundle"
before "deploy:restart", "deploy:migrate"

NOTE: Capistrano provide before and after callback which you can use for chaining different methods of
your deployment script. See the sequence I have created here. deploy:restart method is called after deployment
is done,ie cap deploy command pass successfully. This is a empty method provided by Capistrano to write our server
specific code. But befor starting our server, it is must that our database is migrated. but for migrating database
it is must that all the gems are installed and the database is symlinked properly. Thus , these things are taken
care, by the way we have chained the method

STEP 8: The deployment command
Now, we have perfected our deployment script in STEP  7, so ready to deploy our app anytime with, below two
lines of code

$ cap deploy:setup #need to run only once as it simply set the directory structure and will do nothing if run second time unless you have made some change to deploy:setup
$ cap deploy # run it every time you want to deploy your current code to server after pushing it to git

STEP 9: Starting the Server and Running the APP

I have explained configuring your app with nginx and passenger in this post. You need to restart the server
manually after step 8. I think We can define restart method in our script to do it automatically. I will update the
post once, I confirm it.

Author: arunyadav4u

over 7 years experience in web development with Ruby on Rails.Involved in all stage of development lifecycle : requirement gathering, planing, coding, deployment & Knowledge transfer. I can adept to any situation, mixup very easily with people & can be a great friend.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s