Using Capistrano to deploy to WebFaction
Update
If you like to stay on the edge, check out my latest post describing how to use Capistrano 2.5 to deploy Rails 2.3 to Webfaction!
There’s nothing I love more than sweet automation.
After spending the better part of an hour searching the great Googs, there was only a single blog I could find describing how to use Capistrano to deploy to WebFaction. Unfortunately, Justin was describing a Capistrano 1.4 deployment. I found a few posts on the WebFaction forums, but nothing concrete. So after a few hours fiddling with the technology, here’s how I configured my Rails 2.1.1 project to use Capistrano 2.5 to deploy to WebFaction.
Assumptions
Before getting started, I’m going to assume the following:
- I’m assuming you’ve already used the one-click WebFaction goodness to create a brand new Rails application in ~/webapps/<application_name>. If you don’t know what I’m referring to, make sure to check out the Rails and Typo Demo screencast. Make sure you have a domain, application, and website configured.
- I’m also going to assume that your nifty Rails application is safely stored away in either a Subversion or Git repository and you’ve frozen Rails in your application.
- Finally, I’m going to assume you setup your database via WebFaction’s control panel.
Installing Capistrano
The very first thing you have to do is install Capistrano on your local machine by issuing the following command:
$ gem install -y capistrano
After installing Capistrano, the first thing you have to do is to “capify” your local Rails project. Change into your project’s root directory and issue the following command:
$ capify .
This configures your Rails project to play nicely with Capistrano. Two files should’ve been created; Capfile in the project root and config/deploy.rb. The deploy.rb file contains the Rails project application-specific deployment configuration.
Configuring WebFaction
Jumping back to WebFaction, I followed a few of the steps in Justin’s blog. First thing’s first, ssh into your WebFaction account and create a directory called webapps-releases in your home directory. This directory is where we’re going to deploy the application to.
Since you’ve already configured a Rails application at ~/webapps/<application_name>, change into that directory. You should see a standard Rails project with the exception of an extra file called autostart.cgi. Remove everything in the directory except the autostart.cgi file by issuing the following commands:
$ cd ~/webapps/<application_name> $ mv autostart.cgi ~/ $ rm -rf * $ mv ~/autostart.cgi .
Once the directory is clear, create a symlink to the log directory that will be in the webapps-releases directory we created earlier.
$ ln -s ~/webapps-releases/<application_name>/shared/log ~/webapps/<application_name>/log
Note: I’m assuming here that the WebFaction app and the Rails application have identical names.
Next, open up your favorite editor of choice (*cough*Vi*cough*) and edit the autostart.cgi file. Jump to the end of the file and comment out the following line:
1 2 |
# os.system('/usr/local/bin/mongrel_rails start -d -e production -P /home/<webfaction_username>/webapps/<webfaction_app_name>/log/mongrel.pid -p <port>') |
and right below it, cut and paste the following:
1 2 | os.system('/usr/local/bin/mongrel_rails start -c /home/<webfaction_username>/webapps-releases/<webfaction_app_name>/current -d -e production -P /home/<webfaction_username>/webapps/<webfaction_app_name>/log/mongrel.pid -p <port>') |
Creating your custom deploy.rb
After configuring WebFaction, we have to configure the Capistrano application deployment configuration. On your local machine, find the file config/deploy.rb and replace it with the one below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | set :webfaction_username, "<webfaction_username>" set :webfaction_db_type, "<webfaction_db_type>" set :webfaction_db, "<webfaction_db>" set :webfaction_db_username, "<webfaction_db_username>" set :webfaction_port, "<webfaction_port (get from autostart.cgi)>" set :database_yml_template, "database.example.yml" set :application, "test" set :deploy_to, "/home/#{webfaction_username}/webapps-releases/#{application}" set :scm, :subversion set :scm_user, "<scm_username>" set :scm_password, Proc.new { Capistrano::CLI.password_prompt("Subversion password for #{scm_user}: ") } set :repository, Proc.new { "--username #{scm_user} --password #{scm_password} --no-auth-cache <http://path/to/your/svn/goes/here/>"} set :user, "#{webfaction_username}" set :use_sudo, false set :domain, "<webfaction_domain>" role :app, domain role :web, domain role :db, domain, :primary => true desc "Symlink public to what webfaction expects the webroot to be" task :after_symlink, :roles => :web do run "ln -nfs #{release_path}/public /home/#{webfaction_username}/webapps/#{application}/" end namespace :deploy do # Taken from http://jonathan.tron.name/2006/07/15/capistrano-password-prompt-tips # Thanks Jonathan! :) desc "Creates the database configuration on the fly" task :create_database_configuration, :roles => :app do require "yaml" set :production_db_password, proc { Capistrano::CLI.password_prompt("Remote production database password: ") } db_config = YAML::load_file("config/#{database_yml_template}") db_config.delete('test') db_config.delete('development') db_config['production']['adapter'] = "#{webfaction_db_type}" db_config['production']['database'] = "#{webfaction_db}" db_config['production']['username'] = "#{webfaction_db_username}" db_config['production']['password'] = production_db_password db_config['production']['host'] = "localhost" put YAML::dump(db_config), "#{release_path}/config/database.yml", :mode => 0664 end after "deploy:update_code", "deploy:create_database_configuration" desc "Redefine deploy:start" task :start, :roles => :app do invoke_command "/usr/local/bin/mongrel_rails start -c #{deploy_to}/current -d -e production -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid -p #{webfaction_port}", :via => run_method end desc "Redefine deploy:restart" task :restart, :roles => :app do invoke_command "/usr/local/bin/mongrel_rails restart -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid", :via => run_method end desc "Redefine deploy:stop" task :stop, :roles => :app do invoke_command "/usr/local/bin/mongrel_rails stop -c #{deploy_to}/current -P /home/#{webfaction_username}/webapps/#{application}/log/mongrel.pid", :via => run_method end end |
Otherwise, this file in itself won’t do you any good.
Props out to Jonathan for the fantastic Capistrano tips!
After copying the deploy.rb file and editing the appropriate variables, run the following command in your Rails project’s root directory:
$ cap deploy:setup
This command creates the appropriate directory structure for Capistrano on the deployment server based upon values set in your deploy.rb. Next, run the following command to check your dependencies.
$ cap deploy:check
If everything is successful, you should see a message that reads something like…
You appear to have all necessary dependencies installed
Next, push your code out to the server using the following command:
$ cap deploy:update
Finally, to start up your application run the following Capistrano command:
$ cap deploy:start
Now, you should be able to run the standard Capistrano tasks to deploy your application to WebFaction!
Explanation
Most techies like to have an explanation of what’s going on with the Capistrano deploy.rb. I could probably write another blog about it, but I’m lazy (and pressed for time). The :create_database_configuration task basically writes the database.yml production configuration on the fly (courtesy of this blog posting).
The basic gyst of the rest of the script is that WebFaction is proxying a Mongrel instance. The Capistrano deploy.rb override the original deploy:start, deploy:stop, and deploy:restart tasks to run Mongrel commands that WebFaction can understand. Typically, the default Capistrano tasks run script/spin and reaper, but it was easier just to redefine the task. If anyone has any tips/suggestions to improve the script, I’m all ears!
Voila! (Enjoy)
Popularity: 37% [?]


