With any website, having a regular backup is critical. Heroku, the awesome Rails cloud service that hosts Pocket Tabs and a handful of other sites for me, provides the ability to do backups of code and data through a concept called bundles.

When you enable the free bundles support on Heroku, you only get 1 bundle. You can download it and destroy it to free up the space for the next bundle, but results in 3-4 commands just to get a backup of the site. You can pay for additional bundles, but with a little script we can get by with just one.

Here's the typical workflow:

$ heroku bundles:capture my-site-2010-02-28
$ heroku bundles:download my-site-2010-02-28
#places my-site.tar.gz in the current directory
$ heroku bundles:destroy my-site-2010-02-28

With some help, I created a rake task to do this work for me.

In your rails project, place a new rake file in the `lib/tasks` folder. I called mine `backup_site.rake`. The standard Rails Rakefile knows how to load up any of your custom rake files in this folder. It's a good idea to give your rake tasks a namespace to keep everything tidy. Here's mine:

namespace :pockettabs do
  desc 'Captures a heroku bundle and downloads it.  The downloaded files are stored in backups/'
  task :backup do
    timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
    bundle_name = "pockettabs-#{timestamp}"
    puts "Capturing bundle #{bundle_name}..."
    `heroku bundles:capture --app pockettabs '#{bundle_name}'`
    # poll for completion (warning, a little hacky)
    begin
      bundles = `heroku bundles --app pockettabs`
    end while bundles.match(/complete/).nil?
    # download & destroy the bundle we just captured
    %w(download destroy).each do | action |
      `heroku bundles:#{action} --app pockettabs '#{bundle_name}'`
    end
    `mv pockettabs.tar.gz backups/#{bundle_name}.tar.gz`
    puts "Bundle captured and stored in backups/#{bundle_name}.tar.gz"
  end
end

Now I can easily just run a rake task any time I want to backup the site.

$ rake pockettabs:backup
# Capturing bundle pockettabs-2010-02-28-02-40...
# Bundle captured and stored in backups/pockettabs-2010-02-28-02-40.tar.gz

Next step is to put this in a cron job so that I don't have to remember to do it.