Deploying Rails (2.0) to Mongrel with Capistrano 2.1
Tags: capistrano,
mongrel,
ruby on rails
Posted 26. October 2007.
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:
Also make sure you have installed the latest version of mongrel_cluster on both your production and deployment machine:
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:
/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:
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:
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:
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:
task :restart do
restart_mongrel_cluster
end
end
Your complete deploy.rb could now look like this:
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..
$ 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.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:cold
The Cap task names have changed a little, but you can always see the whole list like this:
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.
Subscribe to this Feed
Social bookmark
Comment on this article
Chris Shen said 189 days ago:
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 => trueHere’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 ipThanks for your help.
Niko said 183 days ago:
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”
Chris Shen said 183 days ago:
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.
Josh Price said 183 days ago:
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 endend
Niko said 177 days ago:
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.
Joe said 76 days ago:
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.
Katherine Doubek said 14 days ago:
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!