Ryan Kanno: The diary of an Enginerd in Hawaii

Everything you've ever thought, but never had the balls to say.

My LinkedIn Profile
Follow @ryankanno on Twitter
My Feed

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
Note: Change all the values in tags like <webfaction_username>, <webfaction_db>, <webfaction_db_username>, etc. to those values that fit your configuration!
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: 28% [?]

  1. Greetings,

    I tried this script but it does not work for me. I can breeze past “cap deploy:check” but “cap deploy:update” gives me this error in authentication.

    …. err] Authentication realm: …

    I have double checked my credentials and they work just fine from terminal.
    What may be causing this issue?

  2. What should the :domain be?
    1. .webfactional.com
    2. (where webfaction site is binding app to domain)
    3. where svn is hosted

    I have tried all of these. Same error.

  3. @ram, the domain should be the domain that your app will be exposed via. If accessing the app through <username>.webfactional.com, then that’s what it should be set to, otherwise, it should be set to your FQDN. For example, I would set it to localkinegrinds.com. I suspect the Authentication Realm error is probably from the access to your SVN repository. How are you accessing your repository? See this Cap mailing list post: http://groups.google.com/group/capistrano/browse_thread/thread/3aaea7539223f8a2

  4. Thanks so much for posting this detailed tutorial on using webfaction with Capistrano. It was exactly what I needed!

  5. @John -

    I’m glad my post helped someone save some time. :)

  6. Hey Ryan,

    Thanks for the detailed instructions, they have been very helpful. I’m very close to getting a successful deployment except that when I run ‘cap deploy:update’, the svn checkout appears to place my rails app in a directory with the Subversion project name *under* the releases/ directory. Because of that, subsequent tasks to find, for instance, public/images fail.

    Any clues? The relevant parts to my deploy.rb are (I believe):

    set :application, “saifa”
    set :deploy_to, “/home2/#{webfaction_username}/webapps-releases/#{application}”

    set :scm, :subversion
    set :scm_user, “wpwood”
    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://my-svn.assembla.com/svn/SaifaDotNet/“}

    and I get a /home2/wpwood/webapps-releases/saifa/releases/20090212180231/ directory containing:

    log public REVISION SaifaDotNet tmp

    I believe that the contents of the SaifaDotNet repository should have been checked out into /home2/wpwood/webapps-releases/saifa/releases/20090212180231/, instead of getting the toplevel SaifaDotNet directory in there.

    Any clues?

    Thanks,
    - Bill

  7. Ah, never mind. It was a problem with my SVN repository structure.

  8. @Bill – I’m glad everything worked out great. :) I haven’t blogged in a few months because of my new job, but this advice would apply to anyone managing a multiple machine deployment in different environments (test, dev, staging, production). If you get a chance, check out capistrano multistage in the capistrano extensions plugin (capistrano-ext). It’s totally awesome. :)

  9. Thanks so much for posting this tutorial! they have been very helpful for me! But I can`t understand why we should write this block of code:

    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

  10. @Roman

    If you remove the after_symlink, does the Rails application deploy? If I sound unsure, it’s because I am. :) I haven’t deployed a Rails application to Webfaction for quite a while. I suspect it’s because of how the Document Root is setup in the Apache conf file. But, that’s just my 50,000 foot guess. If I have time this weekend, I’ll try to drop a Rails application via Cap into Webfaction. :)

  11. [...] for a few years, I absolutely love sweet, sweet automation. A few months ago, I wrote a blog about how to use Capistrano to deploy to WebFaction. However, since that post, the winds of change have swept through the Rails and Capistrano [...]

Please leave a reply »

Powered by Wordpress. Stalk me.