Foreman + Capistrano for Rails 3 applications

Posted by Dan Sosedoff on July 24, 2011

Foreman is a Procfile based process spawner.

Source: https://github.com/ddollar/foreman

Installation

gem install foreman

Configuration

Lets assume you have a resque worker, which you execute with rake:

bundle exec rake resque:work QUEUE=* RAILS_ENV=production

Now, you will need to create a Procfile inside your rails root folder (Procfile):

worker: bundle exec rake resque:work QUEUE=* RAILS_ENV=production

Start your workers with foreman:

foreman start

Foreman will start all of the processes associated with your app and display stdout and stderr of each process. Processes are color-coded by type to make them easy to read. $PORT will be automatically assigned by foreman and made available to each underlying process.

Export to system

While foreman is great for running your application in development, there are some great existing tools for managing processes in production. Foreman can export to either upstart or standard unix init.

Exporting to upstart:

$ foreman export upstart /etc/init

[foreman export] writing: /etc/init/testapp.conf
[foreman export] writing: /etc/init/testapp-web.conf
[foreman export] writing: /etc/init/testapp-web-1.conf

[foreman export] writing: /etc/init/testapp-worker.conf
[foreman export] writing: /etc/init/testapp-worker-1.conf
[foreman export] writing: /etc/init/testapp-clock.conf

[foreman export] writing: /etc/init/testapp-clock-1.conf

Capistrano integration

Assuming you got your capistrano recipe working, here is a set of foreman tasks:

# Foreman tasks

namespace :foreman do
  desc 'Export the Procfile to Ubuntu upstart scripts'
  task :export, :roles => :app do

    run "cd #{release_path} && sudo bundle exec foreman export upstart /etc/init -a #{application} -u #{user} -l #{release_path}/log/foreman"

  end

  desc "Start the application services"
  task :start, :roles => :app do

    sudo "start #{application}"
  end

  desc "Stop the application services"

  task :stop, :roles => :app do
    sudo "stop #{application}"

  end

  desc "Restart the application services"
  task :restart, :roles => :app do

    run "sudo start #{application} || sudo restart #{application}"
  end
end

Just add deploy hooks and its ready to go:

after "deploy:update", "foreman:export"    # Export foreman scripts
after "deploy:update", "foreman:restart"   # Restart application scripts

Documentation