The Absolute Moron's Guide to Capistrano

Posted by brian Thursday, April 05, 2007 19:03:00 GMT

Hamster running

Yeah, we know. If you're just getting started with Rails, and you've been reading all these great articles by all these experienced Rails developers, it's pretty much inevitable. One day, you're going to see this:

You ARE using Capistrano, aren't you?

And you will say, well, no I'm not. I must be a complete idiot.

I admit it. The title of this post is only there to get your attention. No, you're not really a moron. In fact, there are plenty of experienced Rails developers out there not using Capistrano. But the fact is, if you're doing any kind of serious Rails application development, and you're in charge of deploying it (which you probably are), then yes, you should be.

When we .NET developers say that getting into Rails is tough, this is the kind of stuff we're talking about. Learning some basic Ruby in order to develop your first Ruby on Rails application is relatively straightforward for an experienced programmer. It's the Linux shell, server applications, and other things we're not used to that trip us up.

Before we continue, I have to tell you that this guide is for total noobs. There are plenty of great resources to help those experienced with *nix web servers and related technologies get started with Capistrano, including the official manual and the fantastic Capistrano Peepcode screencast (disclosure, a sponsor). However, if you have read this and acknowledge that, indeed, you are a total noob, let's continue.

Theory

The idea behind Capistrano is pretty simple:

  • You haven't been spending all of your time developing that next great Web 2.0 application in Rails for nothing. You're ready to push said application out to the ol' "series of tubes".

So, if you didn't have Capistrano, you might do one of the following to get your code to its production environment:

  • FTP your whole Rails app over.
  • Use subversion to version control your app, then when you're ready, shell out via SSH to your production server (using PuTTY, perhaps), and get the code by checking-out/exporting from your repository.

Needless to say, both approaches are *so* not cool anymore. Not to mention that, in addition to getting your code where it needs to go, other things might need to get done - like restarting your web server, making some changes to your database, or cleaning stuff up. That said, all Capistrano basically does is automate the SSH-subversion-checkout method and lets you add whatever else you might need from there.

One important thing of note: Capistrano is a utility that runs on your workstation, not on the server. Therefore, there is nothing special that you have to do on the server-side to make it work. I'm surprised by the number of people I meet who misunderstand this, hence the yelling. The whole idea of Capistrano is to automate the most common tasks you might shell into your server to perform, to make sure you hardly ever have to shell into your server again. (In case you were wondering, it uses the Ruby Net-SSH library to do all the talking, so you don't need any particular SSH client installed either.)

Installation

Capistrano is distributed as a RubyGem, and as such, that's the easiest way to install it.

gem install capistrano --include-dependencies

After the Capistrano gem is installed, you use the newly available cap command to add a deploy.rb file to your Rails application's config directory. A lot of the guides out there will refer to this as "applying" Capistrano or "Capistranizing" your application... all you're doing is copying the one file to the config directory. Head over to the root directory of your Rails application, and type:

cap --apply-to .

The deploy.rb file (the "recipe")

The deploy.rb that gets created for you is a file that's often called the deployment "recipe". That's because, in many ways, it is indeed a "recipe" that describes how to assemble all the pieces that you need to run your application in production. Capistrano then takes your recipe and makes it all happen in one fell swoop.

The example code that's written to the deploy.rb includes a bunch of stuff by default, most of which you probably don't need for a basic deployment scenario. That said, it's a good idea to go through it and see what some of the options are. For the purposes of this exercise, here's our (very) minimal deployment recipe:


set :application, "softiesonrails"
set :repository, "http://somesvnrepository/trunk"
role :web, "mygreatrailsapp.com"
role :app, "mygreatrailsapp.com"
role :db, "mygreatrailsapp.com"

What's this recipe going to do when we run it? (We'll talk about how to actually run it in a moment.) Let's dissect it a bit.

  • By specifying role :web "mygreatrailsapp.com", you're telling Capistrano that "mygreatrailsapp.com" is the server to which you'd like to deploy your application. You can obviously set different values for the various machines you may have set up in a more advanced situation; we're just using the same server for all roles (web, app, and database) here.
  • By default, Capistrano will create a folder at /u/apps/ and stick your application code in there. So, in this case, a folder called /u/apps/softiesonrails will be created, since we've specfied "softiesonrails" as the name of our application. Then, a subdirectory, current, is where the latest version of your application lives. On a shared host (say, Dreamhost) you would have to override this setting and provide the full path to somewhere underneath your home directory. For example:
set :deploy_to, "/home/your_username/apps/softiesonrails"
  • Capistrano works by SSH'ing out to your server and running some commands. In this case, here's what will happen once an SSH connection to "mygreatrailsapp.com" is established:
    • Take any code that's already in /u/apps/softiesonrails/current and archive it (a new directory that's unique by date and time will be created and the code moved there).
    • Check-out the latest source code from your subversion repository to the currentdirectory.

Time to deploy

Ok, your recipe is now set up, and you're ready to actually deploy your application. The very first time, you'll want to run:

cap setup

What this will do is SSH to your server, asking for a password first, and create the necessary directory structure and permissions for you. If you take a close look at the output of this command, you'll see the actual commands being executed. Don't worry if this fails the first time, just fix any errors that appear and give it another shot. Once the setup is complete, you can run your deployment recipe:

cap deploy

If you're really a total noob (and you probably are if you're still reading this), there's a good chance it will fail the first time. Not to worry, here are just a couple of troubleshooting tips:

  • By default, Capistrano will try to use the same username on your subversion repository as you've specified for access to the server. You can easily override this by specifying the login credentials in the recipe:

set :svn_username, "brian"
set :svn_password, "secret"

  • Your deployment may stall on asking for a subversion password. That's because, even if your subversion and server usernames match, the server is going to need to authenticate against your repository if it never has before. To do this (you only have to do this once), simply SSH to your server manually, go to a temporary directory, and check-out or export something (anything) from your repository. You'll be asked for credentials and be authenticated from that point forward.

What's Next

The basic recipe we've discussed here might just be enough for a lot of people to get started. What you do from here is highly dependent on your specific server setup (i.e. whether you're deploying on Apache, FastCGI, Mongrel, Litespeed, Nginx, a rack of hamsters, etc.) If you're hosting with one of the major hosting companies supporting Rails, you'll usually find some documentation on Capistrano on your hosting company's support area as well.

Bottom line: dive right in. You'll find it much less intimidating and daunting a task than it may seem at first. And, just like everything else with Rails, once you get comfortable with it, you'll wonder why you ever deployed your application any other way.

Image credit: Seattle Roll

Comments

Leave a response

  1. Bradly   April 06, 2007 @ 05:59 AM

    Every time I tried to read a Capistrano tutorial before, the level of assumed knowledge had always been just beyond me. This article was a breath of fresh air.

    -Bradly

  2. Frank   April 06, 2007 @ 01:24 PM

    Excellent tutorial! Very clear, short and to the point.

  3. Bill   April 06, 2007 @ 03:14 PM

    Nice "Continue Reading..." link

  4. Danila   April 06, 2007 @ 11:36 PM

    Thanx a lot! Ive read it at one breathe! Ill suggest this article to friends.

  5. Paul   April 07, 2007 @ 05:26 PM

    Thank you for a this wonderful tutorial. I had an idea of what Capistrano was, a deployment app, etc... but no one could tell me why I needed it, what it could do for me, how I could leverage it; you answered all of these questions and more.

    I'm recommending this tutorial to anyone interested in Rails development.

  6. Charles   April 07, 2007 @ 05:56 PM

    Fantastic. Thanks for making it clear and simple.

  7. Moron   April 07, 2007 @ 09:45 PM

    Thanks. It makes sense now!

  8. Nikhil   April 08, 2007 @ 09:21 AM

    Why do we need the "db" role? Even if we run the migration scripts from the app server, wouldn't it still get executed on the db server (since the db connection points to it)? By requiring migrations to run on db, we unnecessarily need to install the entire app along with gem dependencies on the db server.

  9. [developer, sysadmin, customer].each {|person|   April 08, 2007 @ 01:44 PM

    puts person.name + ": thanks!!!" }

  10. Chad Burt   April 09, 2007 @ 03:15 PM

    "Why do we need the "db" role?"

    Yeah, I'm with you Nikhil, what is up with that? Capistrano assumes you use a single username/password that can be used on everything, even your database server. It should be able to accomplish everything from within the database, not a shell account.

    It seems to me that capistrano is only useful for deploying on a dedicated set of machines, which seems unrealistic to me. How many organizations are deploying a dedicated set of servers for rails compared to how many are slowly testing the waters on existing infrastructure?

    I'm setting up everything manually now, and doing updates via svn update. Seems fine to me, and that is what I would recommend to those new to deployment.

  11. Donovan Dillon   April 10, 2007 @ 08:19 AM

    Excellent article at just the right level for this newbie Brian. Thank you! You make references to subversion, but do not explicitly state that it *is* a requirement. My assumption is that it is. Can you please confirm? If it is, any chance of a similar newbie tutorial on how to setup subversion on your app site?

  12. Brian Eng   April 10, 2007 @ 02:31 PM

    @Nikhil: You're right, I don't see why the migrate task requires the db role to be specified, either, since it is simply running rake:db:migrate from the app server, based on your application's config. However, it does make sense to me why you'd want to specify it anyway in your recipe. The recipe is meant to describe your deployment landscape as a whole, and as such, you'd want to have your db server in there, in case you'd want to perform specific tasks on that server alone.

    @Donovan: Good question. AFAIK, Subversion is not a requirement to use Capistrano, but all the built-in deployment tasks use it. Theoretically, you could write your own recipe that is comprised of all custom tasks, without the use of any SCM at all... but it would kinda defeat the purpose, I think :) As far as Subversion resources, there a bunch of Subversion cheat sheets online (just ask your ol' pal Google), but I'd highly recommend the Pragmatic Version Control book... it's how I got a clue about subversion.

  13. JonR   April 10, 2007 @ 02:39 PM

    thanks! i'm going to try this as soon as i get home!

  14. anthony   April 25, 2007 @ 09:17 PM

    the reason that the DB role is a good idea is if you have multiple app servers - you probably don't want to run all database tasks once per app server

  15. Andrew   April 30, 2007 @ 03:17 PM

    This is excellent - thank you for taking the time to put this together.

  16. John   May 03, 2007 @ 12:52 PM

    Thanks for making it clear that there are no Capistrano parts on the server. I have been struggling with that trying to deploy to a hosting company that supports RoR but is clueless about Cap.

  17. Sam   June 11, 2007 @ 08:27 PM

    As for ssh to svn checkout vs capistrano, I prefer capistrano because of the way it uses symlinks for an atomic update. An svn checkout with a running app will create a mixed version with classes cached in memory vs disk until you manually restart the app.

  18. Peter   July 23, 2007 @ 04:15 PM

    Hi, set :svnusername and set :svnpassword don't work for me (Capistrano v1.4.0). It connects to SVN using same user as the one on the Apache server where it is deploying.

    Any ideas, please?

  19. Ben Nevile   August 08, 2007 @ 08:02 PM

    as of version 2.0, the --apply-to no longer works. Instead, use

    capify .

  20. Christopher L Petersen   August 09, 2007 @ 11:59 PM

    It does seem unnecessary to checkout the app to the database server, it would be nice for Capistrano to connect and run the scripts remotely.

    A side effect of running the scripts locally on the db server is that it must have Ruby, Gems, and Rake installed. Not a big deal if you are deploying your app and database to the same server, but I found it kind of odd that I had to install all that on my database server (which is intentionally bare boned).

    Capistrano is a great tool. Thanks for the tutorial.

    Chris

  21. depot   August 17, 2007 @ 09:18 AM

    thank you for taking the time to put this together.

  22. Jeff Dean   September 13, 2007 @ 08:48 AM

    You can apply a few simple fixes to avoid deploying the app to and running migrations from the database server.

    First, add :no_release=>true to the database server and make one of your app servers the primary one, like so:

    role :app, 'app_server', :primary => true role :db, 'mysqlserver', :primary => true, :norelease => true

    This will exempt it from the default checkout tasks.

    Next, go through your gems directory and find the set of default tasks for your version of capistrano and copy it to your deploy.rb file, then change the roles. I'm on 1.4.1, so it looks like so (I apologize in advance if the formatting gets wonky):

    task :migrate, :roles => :app, :only => { :primary => true } do directory = case migratetarget.tosym when :current then current_path when :latest then current_release else raise ArgumentError, "you must specify one of current or latest for migrate_target" end

    run "cd #{directory} && #{rake} RAILSENV=#{railsenv} #{migrate_env} db:migrate" end

    Notice how I just changed the role to be the app server, not the db server.

    Now cap -a setup, cap -a deploy and cap -a migrate all work as expected, with no need to have ruby on your mysql server.

    Cheers

  23. Jeff Dean   September 13, 2007 @ 08:57 AM

    Boy I dislike markdown in comments - here's hoping this one comes through a little better:

    task :migrate, :roles => :app, :only => { :primary => true } do
      directory = case migrate_target.to_sym
      when :current then current_path
      when :latest  then current_release
      else
        raise ArgumentError, "you must specify one of current or latest for migrate_target"
      end
      run "cd #{directory} && #{rake} RAILS_ENV=#{rails_env} #{migrate_env} db:migrate"
    end
    
  24. Ben Knight   September 15, 2007 @ 01:46 PM

    A couple of our developers are using Windows and can't capistrano to get past the 2nd (or 3rd) password request when doing a "deploy" or "deploywithmigrations" -- everything else such as restart_app, etc. work fine. Any advise/suggestions?

    I was using Windows at one point and was able to get capistrano working on my dell laptop but cannot for the life of me remember how it worked. All I recall is that I had to do a "echo password|cap deploy" and it worked. Apart from the standard Ruby/Rails stuff, I had cygwin, openssh and subversion command line utilities for windows.

    Any help would be greatly appreciated!! And please, switching from windows isn't an option for us at this point.

    Thanks in advance.

  25. Onno   December 13, 2007 @ 10:24 AM

    It worked for me with cap 1.4.1, I upgraded to 2.1.0 and can't get it to work anymore.

    The stuff is hard. It will take me the better part of today maybe tomorrow to get it to work. Actually, I might have to give up on Capistrano option all together.

    At least from Windows to Linux Capistrano this is just messy!

  26. Spongebob Squarepants   December 22, 2007 @ 09:34 AM

    Nice. Thanks

  27. Matthias   January 10, 2008 @ 05:32 PM

    @Jeff Dean: Thanks for your solution for overwriting the migrate task. I don't like copying the default but I can live with it. Note that with capistrano 2.1.0 you have to put a namespace :deploy do ...end around your overwritten deploy task!

  28. PaweÅ‚ R.   January 31, 2008 @ 09:32 PM

    Very good article but when I type:

    cap --apply-to .

    I get error message on Windows XP box saying: "You are running Ruby 1.8.6, which has a bug in its threading implementation. You are liable to encounter deadlocks running Capistrano, unless you install the fastthread library, which is available as gem: gem install fastthread"

    After installing fastthread with above command I still can't use: cap --apply-to .

    Any ideas why? Any help much appreciated! Thanks in advance!

  29. Reinhart   February 17, 2008 @ 04:25 PM

    Pawel, you use capistrano 2.x, you can use command "capify", but not "cap --apply-to" and the next instruction is little bit different, you can email me for more instruction.

  30. aditya   May 02, 2008 @ 08:38 AM

    thank’s for neat article… i understand now that capistrano running on the client not on the server

  31. Melinda Slade   July 18, 2008 @ 07:55 PM

    I hate it when someone thinks or ass-u-me’s that you know something about what they are talking about when I don’t. You made it understandable for most everyone that has a little or even not much knowledge at all. It’s nice to see there’s someone out there that is really trying to teach instead of talk over others heads.

    Love it, Melinda

  32. psmn0ux6al   September 24, 2008 @ 10:48 PM

    t08×0ry0o http://www.767030.com/543247.html wbwzjtt4r2k

  33. zgkklm   October 07, 2008 @ 02:25 PM

    eviqttxsydikoxadsuimfmwobrmzuo