Deploying Rails (2.0) to Mongrel with Capistrano 2.1

Tags: , ,
Posted 2039 Tage zuvor.

Capistrano 2.1 includes some major improvements over the 1.x branch, so everyone should start using it right away. Yet it doesn't work with Mongrel out of the box and it's most likely not backwards compatible with your old deploy recipes. Since there is no official documentation on how to get going with Rails and Mongrel, I put together these instructions.

What follows is a compilation of tips and hacks from mailing lists and different places on the internet that should help you get your Rails app deployed with Capistrano 2.1 in no time.

I have only tested this with Edge Rails (RC1), but it should work the same with your stable Rails 1.2.5 projects.

I assume that you have already setup up Apache and a Mongrel cluster on your web server, as it is described in many places on the net and that you are using Subversion to manage your code base.

First, if you haven't already done so, install or update Capistrano:

$ sudo gem install capistrano

Also make sure you have installed the latest version of mongrel_cluster on both your production and deployment machine:

$ sudo gem install mongrel_cluster

I advise you to have a quick look at the "Getting started with Rails" section on the Capify website, at least the two paragraphs entitled "Enabling Capistrano" and "Project Details". They tell you how to capify your app and show you how your basic config/deploy.rb could look like (It doesn't work yet, though). The rests of the page was not so helpful to me and provides little detail for our specific task, you may safely skip it for now.

First you need to create a spinner script that will start your mongrel servers the first time you deploy. Create a file in you Rails project named "script/spin" and add the following line, replacing "/path" with the real path to your Rails app on the production server:

# File: script/spin
/usr/bin/mongrel_rails cluster::start -C /path/current/config/mongrel_cluster.yml

You now have to make the spin script executable on the web server to avoid error messages like "script/spin: Permission denied". This is done easiest with subversion. Issue the following command in you working copy:

$ svn propset svn:executable on script/spin

In your config/deploy.rb, tell Capistrano where to find your mongrel config, assuming deploy_to is set the path of your app on the server:

set :mongrel_conf, "#{deploy_to}/current/config/mongrel_cluster.yml"

When I did the cold deploy, I got the following error. Turns out, probably some 37 signals employee forgot to remove private configuration from the code:

command "sudo -p 'sudo password: ' -u app sh -c 'cd /path/to/my/rails/app/current && nohup script/spin'" failed on domain.com

This should be fixed eventually. For now, add the following line to your config/deploy.rb:

set :runner, nil

Also, the restart task doesn't get executed from mongrel_cluster recipes but instead tries to spawn a FastCGI process when deploying, add this line to your config/deploy.rb to bring things back on track:

namespace :deploy do
  task :restart do
    restart_mongrel_cluster
  end
end

Your complete deploy.rb could now look like this:

require 'mongrel_cluster/recipes'

set :application, "myapp"
set :repository,  "http://my.svnserver.com/svn/myapp"
set :deploy_to, "/path/to/my/rails/#{application}"
set :user, "root"
# Thew new way of telling capistrano 2.1 to use export rather than checkout
set :deploy_via, :export
set :runner, nil
set :mongrel_conf, "#{deploy_to}/current/config/mongrel_cluster.yml"

role :app, "domain.com"
role :web, "domain.com"
role :db,  "rdomain.com", :primary => true

namespace :deploy do
  task :restart do
    restart_mongrel_cluster
  end
end

I haven't yet figured out how to use sudo in cap 2.1, so I deploy using root. You could also set :user to an unprivileged user that has write access to your apps releases directory. Don't forget to manually svn checkout on the production machine with the user specified here before you deploy the first time, or else the deploy will fail.

For completeness, here's a sample mongrel_cluster.yml:

---
cwd: /path/to/my/rails/app/current
log_file: log/mongrel.log
port: "7000"
environment: production
address: 127.0.0.1
pid_file: tmp/pids/mongrel.pid
servers: 2

To ged rid of the deprecation warning when deploying I followed the instructions found in comment #18 on Jamis Buck's weblog. Find the mongrel_cluster recipes file on your system..

$ locate recipes.rb # Or, if that doesn't work:
$ find / -name recipes.rb

.. and comment out the first line, replacing it with two new lines, so the beginning of the file looks like this:

configuration = Capistrano::Configuration.respond_to?(:instance) ? Capistrano::Configuration.instance(:must_exist) : Capistrano.configuration(:must_exist)
configuration.load do
# Capistrano.configuration(:must_exist).load do

Hopefully this will be fixed in the mongrel_cluster gem soon, but until then this quick hack will do.

Now you are ready to go. Setup your basic directory structure, fire up mongrel, and start deplyoing..

$ cap deploy setup
$ cap deploy:cold

The Cap task names have changed a little, but you can always see the whole list like this:

$ cap -T

I tested many common tasks such as deploy, deploy:migrate, deploy:disable:web and restart. All of these should now work with the configuration above. I hope I haven't forgotten anything. If you still get errors when setting things up, please drop a comment and I will try to help you out.

SubscribeSubscribe to this Feed

Save to: Del.icio.us Save to: Google Save to: Facebook Save to: StumbleUpon Save to: Slashdot Save to: Technorati



Comment on this article [10]

  1. Tim Littlemore () said 1952 Tage zuvor:

    Thank you so much for this!

    I have tried several times to get Capistrano 2 to work with Rails apps and have usually lost patience and downgraded back down to capistrano 1.4.1.

    This time I decided to persevere and stumbled across your article, which has finally got things working for me. Why it’s so difficult to get the new capistrano to work with a mongrel deployment, I will never know – surely, this is what most people are deploying??

    Thanks again.

  2. Chris Shen () said 1941 Tage zuvor:

    I’m getting stuck at deploy cold. I’ve done a local checkout via ssh, capified, and committed changes. I’ve also done a checkout on the remote and edited permissions just in case, sudo from remote was the issue. It’s rolling back around /app/releases/

    Both machines on ubuntu.

    Here’s my deploy.rb:

    require ‘mongrel_cluster/recipes’

    set :application, “x”
    set :user, “y” # user belongs to group with rws permissions
    set :domain, “ip”
    set :repository, “svn+ssh://svn1/home/svn/#{application}/trunk”
    set :use_sudo, true

    # If you aren’t deploying to /u/apps/#{application} on the target # servers (which is the default), you can specify the actual location # via the :deploy_to variable:
    set :deploy_to, “/home/apps/#{application}”
    set :deploy_via, :export # tried checkout as well
    set :runner, nil
    set :mongrel_conf, “#{deploy_to}/current/config/mongrel_cluster.yml” # set :chmod755, “app config db lib public vendor script script/* public/disp*”

    ssh_options[:keys] = %w(/absolute/path) # If you are using ssh_keys # default_run_options[:pty] = true

    # If you aren’t using Subversion to manage your source code, specify # your SCM below: # set :scm, :subversion

    role :app, domain
    role :web, domain
    role :db, domain, :primary => true

    Here’s the log:

    * executing `deploy:cold’ * executing `deploy:update’ ** transaction: start * executing `deploy:update_code’ * executing “svn export -q -r3 svn+ssh://svn1/home/svn/x/trunk /home/generic/apps/x/releases/20080201070337 && (echo 3 > /home/generic/apps/x/releases/20080201070337/REVISION)” servers: [“ip”] [ip] executing command ** [err] svn: Error in child process: exec of ‘/etc/ssh’ failed: Permission denied command finished *** [deploy:update_code] rolling back * executing “rm -rf /home/generic/apps/x/releases/20080201070337; true” servers: [“ip”] [ip] executing command command finished command “svn export -q -r3 svn+ssh://svn1/home/svn/x/trunk /home/generic/apps/x/releases/20080201070337 && (echo 3 > /home/generic/apps/x/releases/20080201070337/REVISION)” failed on ip

    Thanks for your help.

  3. Niko (http://www.rubyrobot.org) said 1936 Tage zuvor:

    Chris, sorry for the late response. Comment notifications always get lost in my Google Mail spam filter.

    The error seems to be in your deploy.rb. If you define :repository as a svn+ssh connection, you must give it the full server name and path, i.e. “svn+ssh://host.example.com/repos/project”

  4. Chris Shen () said 1935 Tage zuvor:

    no worries, thanks for the reply. im using an alias “svn1” to access my repo b/c my ssh is set to a non-standard port. unfortunately, svn doesn’t conform to the standard ip:port hence, the alias. so from local, this command does work : “svn co svn+ssh://svn1/some/more/paths/trunk”, but this cmd wont work through capistrano and also fails when i execute it on the server.

    i use public/private keys to access ssh and i think it might be getting in the way of capistrano, but im not sure why.

  5. Josh Price () said 1935 Tage zuvor:

    Great post! Saved us a bunch of time. One issue though:

    The deploy:restart task is already defined correctly in mongrel_recipes for cap 2.0 and therefore doesn’t need to be added. Removing this made everything work!

    namespace :deploy do

    task :restart do restart_mongrel_cluster end

    end

  6. Niko (http://www.rubyrobot.org) said 1929 Tage zuvor:

    Chris: Hope you already have sorted it out by now. If not: I don’t know how you defined your alias, but the SSH shell executed by Capistrano doesn’t share your user’s environment (variables). Googling “svn+ssh capistrano” gives some promising results, too.

  7. Joe () said 1828 Tage zuvor:

    I’m sure Chris won’t see this, but for the benefit of others the problem almost certainly is that the ssh binary is not /etc/ssh. On boxen I have checked, /etc/ssh is a directory containing config files for the ssh server. The ssh client binary is typically /usr/bin/ssh, or perhaps /usr/local/bin/ssh.

  8. Katherine Doubek (http://fragmentedzen.com) said 1766 Tage zuvor:

    That “set :runner, nil” trick was a lifesaver. I’m running on Capistrano 2.4.3, and that glitch is still there.

    Thanks for writing this!

  9. ndgiang84 () said 1279 Tage zuvor:

    have you found a way to run with another user than “root” ?

  10. metin2 (http://www.onlymetin2.com) said 934 Tage zuvor:

    Thank you so much for this!

Don't even bother spamming, comments are moderated.
Textile-Hilfe