Deploying a Rails app used to suck. Reverse proxies, Mongrel clusters, Monit, etc. Capistrano helped out a lot (once you set it up the first time), but all in all the process was still pretty painful.

Thankfully, a couple of technologies have come along and made my deployment process a whole lot easier.

  1. Passenger This was the big one. The Phusion guys’ “Hello World” app (as they called it) has really had a positive impact on the Rails community, and me personally. Suddenly my Rails (and Rack) web apps are first class citizens to Apache (and Nginx), which means I can just point a virtual host at the public directory and go. I had almost forgotten how good it feels to just drop some files in a directory and have Apache serve them.

  2. Git Ok, so maybe Subversion allows a similar workflow, but for some reason Git is one of those tools that is so much fun to use that it makes me think of different ways I can use it.

My Flow

How I deploy these days (when I’m not deploying to Heroku) is dead simple. I host my private Git repos using Gitosis, but the same would work with GitHub or any Git server.

Initial Setup

  1. Clone the repository on production server.
  2. Create database.yml and any other production-specific configs
  3. Configure an Apache virtual host pointing to “public” folder of the repository

Deploys

locally:

jerod@mbp:~$ git push origin master

remotely:

jerod@mbp:~$ git pull origin master && touch tmp/restart.txt

I know what you’re thinking, “Wow, that is dead simple”. It’s even easier by using Capistrano to execute the remote commands. Here is an example Capistrano task from one of my Rails apps:

task :deploy, :roles  => :production do
  system "git push origin master"
  cmd = [ "cd #{root_dir}", "git pull", "touch tmp/restart.txt" ]
  run cmd.join(" && ")
end

This task can be extended to automatically install required gems, update Git submodules, migrate the database, and so on.

Other Benefits

Besides the simplicity and ease of deployment in this process, I have also enjoyed the ability to make edits in production and pull them back in to my development environment. And because my production environment has a complete history of code changes, it is trivial to revert commits that cause major problems.

This work flow is by no means a panacea. How do you handle deployment?