I have been developing DuZhe Text Analyzer using Ruby on Rails 3 (since it is my preferred method of developing backend for online applications) over the last month or so.  Since this is longer than a 20-minute application, I decided to use a version control system, git.  I intend to roll out features continuously so a good deployment strategy is very important for me.  I decided to use Capistrano for no particular reason other than the flexibility it offers to deploying rails applications.

Finally, to run the Rails 3 app, I’m using Passenger (mod_rails) to execute the ruby code.  I’ve chosen Passenger because it is the fastest option for executing Ruby apps offered by my web hosting provider.

Getting all 3 components to work together, unfortunately, was not trivial.  It took a while to get it all to work because primarily there is not much documentation on generating a recipe for Capistrano that works with Rails 3.

Here is a step by step on how to get Ruby on Rails 3 deployed on Passenger-enabled servers with git and Capistrano.

1. Set Up Git Repository

I will not go into how to install git on the server and locally; that is for another tutorial.  I recommend to make sure the git locally and remotely are of the same version or some unexpected bugs may arise.

First, make a copy of your project, just to be safe, then change directory to the project directory:

[localuser ~]$ cd projectdir

Now that we are in the right folder, let’s set up the project as a local git project.  First, let’s look at all the steps and analyze them one by one:

[localuser projectdir]$ git init
[localuser projectdir]$ touch .gitignore
[localuser projectdir]$ git add .
[localuser projectdir]$ git commit

The first line tells git to initialize this folder as a repository.  After it is done, we create an empty .gitignore file.  This is where you can write what files to include from the repository.  I’m leaving it blank for now.  Next I let git know to add all the files in the directory to the local repository (note the “.” at the end; it can be replaced for specific files).  Finally, I let git know to commit any changes (which in this case would be everything).

Now we need to switch over to the remote server and and set up a remote repository:

[localuser projectdir]$ ssh [remoteuser@]host
[remoteuser ~]$ mkdir projectdir.git
[remoteuser ~]$ cd projectdir.git
[remoteuser projectdir.git]$ git init --bare
[remoteuser projectdir]$ exit

First, we SSH into the remote server and create a new directory where we want the remote files to be stored.  We initialize the directory as a barebones git repository, since there are no files there yet.  Finally we return back to the local machine.

Next we are going to push our local repository to the remote host and set up some short cuts to make it easier in the future:

[localuser projectdir]$ git remote add origin ssh://[user@]host/~/projectdir.git
[localuser projectdir]$ git push origin master
[localuser projectdir]$ git branch --set-upstream master origin/master

In the first line we set up a short cut to push the repository to keyword: origin, rather than typing the address every single push.  Next we push the previous commitment to the “origin” server under master branch.  Finally, we set up our branch is the primary upstream branch, so we can just issue “git push” command without specifying a branch or remote host.

2. Set Up Capistrano

Capistrano is a wonderful program for deploying Rails 3 apps; it allows for great customization and is very simple to use.  Best of all, it is very flexible and will work with almost any version control system out there.  Of course, we will be using it with git, so we will develop the right recipe for that.

The first step is to install Capistrano with the following command:

[localuser projectdir]$ gem install capistrano

After the installation is done, open up your Gemfile and add:

gem 'capistrano'

Finally, we initialize Capistrano by running:

[localuser projectdir]$ capify .

This creates two files Capfile and config/deploy.rb.  The Capfile is like a a make file and can be left alone.  The second file, config/deploy.rb, is the one that we will customize.  Fill in all the necessary information that is representative of your connection:

require 'bundler/capistrano'
set :user, 'username'
set :domain, 'web.host.com'
set :applicationdir, "appdir"

set :scm, 'git'
set :repository,  "ssh://[user@]host/~/projectdir.git"
set :git_enable_submodules, 1 # if you have vendored rails
set :branch, 'master'
set :git_shallow_clone, 1
set :scm_verbose, true

# roles (servers)
role :web, domain
role :app, domain
role :db,  domain, :primary => true

# deploy config
set :deploy_to, applicationdir
set :deploy_via, :export

# additional settings
default_run_options[:pty] = true  # Forgo errors when deploying from windows
#ssh_options[:keys] = %w(/home/user/.ssh/id_rsa)            # If you are using ssh_keysset :chmod755, "app config db lib public vendor script script/* public/disp*"set :use_sudo, false

# Passenger
namespace :deploy do
  task :start do ; end
  task :stop do ; end
  task :restart, :roles => :app, :except => { :no_release => true } do
    run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
  end
end

The first line is very important for making Capistrano work with Ruby on Rails 3.  Without it, Capistrano will throw a bunch of errors when running the bundler on the remote host.  Line 2-4 are relevant to your server configuration and should be filled in accordingly.  Lines 6-11 set up git as the version control system; you should adjust line 7 for where you set up the remote repository in the previous section.  Lines 14-16 set up the addresses of the different services (all the same in this case), and line 19-20 set up the deployment location.  Finally, lines 27-33 let Capistrano know that we need to create a file tmp/restart.txt to reboot Passenger after any deployment.

This pretty much all you need to do to get it deployed:

[localuser projectdir]$ cap deploy

That’s all it takes to get the app deployed.  Leave a comment and let me know if this worked for you :)

Tagged with:
 
  • http://fernandoaureliano.com Fernando Aureliano

    Hi!!

    Great tutorial.

    But I’m getting this error:

    failed: “sh -c ‘git clone –depth 1 ssh://fernandodz3@teste.celsoetaniadiniz.com.br/~/projectdir.git foreverd/releases/20110526220312 && cd foreverd/releases/20110526220312 && git checkout -b deploy a1385bb0433c977408d1a054936fba3d08e4f852 && git submodule init && git submodule sync && git submodule update –init –recursive && rm -Rf foreverd/releases/20110526220312/.git && (echo a1385bb0433c977408d1a054936fba3d08e4f852 > foreverd/releases/20110526220312/REVISION)’” on teste.celsoetaniadiniz.com.br

    do you know why?

    thanks by the help!

    • Y Kamesh Rao

      I am getting the same error. Could you resolve it? How?

    • Andy

      @Fernando Aureliano

      because the path to bundler is not set correctly or not found. try adding a section like this:


      set :default_environment, {
      'PATH' => "/home/aw/.rvm/gems/ruby-1.9.2-p180/bin:/home/aw/.rvm/bin:/home/aw/.rvm/environments/ruby-1.9.2-p180/bin:$PATH",
      'RUBY_VERSION' => 'ruby-1.9.2-p180',
      'GEM_HOME' => '/home/aw/.rvm/gems/ruby-1.9.2-p180',
      'GEM_PATH' => '/home/aw/.rvm/gems/ruby-1.9.2-p180',
      'BUNDLE_PATH' => '/home/aw/.rvm/gems/ruby-1.9.2-p180' # If you are using bundler.
      }

      • Andy

        ah … sorry – did not read the error message enough. Forget my comment (not possible to clear or update it) ….

  • Alex

    Hi,

    I am getting this error:
    ** [deploy:update_code] exception while rolling back: Capistrano::ConnectionError, connection failed for: sadalbari.dreamhost.com (Errno::ENOMEM: Cannot allocate memory – connect(2))

    I have run the cap deploy:check and everything is fine. But then after I run the cap deploy:update I get that error.

    Any help would be appreciated!

    Thanks!

  • Seamus

    Thank you for the very straight-forward explanation. It helped me a lot.

    :D

  • Avin Tokade

    Really Very Nice Article.

    I have query.
    1) Need to commit my Capistrano generated files(deploy.rb, Capfile) in project git repository before cap deploy?

    • Avin Tokade

      One more doubt
      2) Need to commit Gemfile.lock file ?
      I use Git as SCM

  • http://jez.caudle.me.uk Jez Caudle

    Wow! I have been trying to get my head around this for years. This is the most concise and informative guide I have ever seen. They usually waffle on about SSH keys and setting up Git. One guide claimed you needed a Git repository that could be read from the server.

    I’m going to give this a spin tonight on my latest project.

    Thank you so very much.

    • http://jez.caudle.me.uk Jez Caudle

      I got an error when Cap ran the ‘bundle’ so I did it by hand instead and re-ran the deploy and it all worked!!

      Massive thanks. I can now delve deeper into Git and it’s branching and the different Capistrano commands knowing that the basics work.

      4 or 5 years I’ve been trying to understand and this and get it working but like I said most guides get bogged down in waffle. Not here!

  • Emiel

    Thanks! Worked great for me.

  • demonchand

    Great tutorial.

    Thanks :)

  • http://www.facebook.com/profile.php?id=757635703 Matt Bessey

    This guide is one line off perfect for my needs. And it took me a good 48 hours of thinking to work out what need changing… If you have your private / public key pair stored locally, you will need to add this line. 
    ssh_options[:forward_agent] = true
    I don’t fully understand why, but it seems to work! As advised by github:
    http://help.github.com/deploy-with-capistrano/

  • Shareef Ddkl369

     i am getting these error please resolve me
    failed: “sh -c ‘cd /var/www/edupdu.com/public_html/demo/releases/20120505100624 && bundle install –gemfile /var/www/edupdu.com/public_html/demo/releases/20120505100624/Gemfile –path /var/www/edupdu.com/public_html/demo/shared/bundle –deployment –quiet –without development test’” on edupdu.com

    • Carlos Eduardo

      same error here

  • Manu Datta

    Awesome! Two thumbs up.

  • Tomáš Vik

    appdir have to be fullpath, it took me 30 minutes to figure it out

  • Антон Ермоленко

    i get this error when i try to deploy:

     executing locally: “git ls-remote ssh://h41319@h33.hvosting.ua/~/www/elmor.org.uan  master”
    sh: 2: master: not found

    and i’ve followed instructions.
    Only added 
    cap deploy:setup
    and it created working dirs on ssh server

    • Anonymous

      Make sure your path after the domain is correct, you may want to use an absolute path instead of ~.

  • Антон Ермоленко

    i get this error when i try to deploy:
     executing locally: “git ls-remote ssh://h41319@h33.hvosting.ua/~…n  master”sh: 2: master: not found
    and i’ve followed instructions.Only added cap deploy:setupand it created working dirs on ssh server

  • Suryakant Maurya

    Thanks!!! Awesome information