February 25, 2012

Using foreman and supervisord for process monitoring

note: this post was updated on 05.03.2012 to reflect changes made to supervisord support.

When I’m developing a Ruby on Rails application I like having my external services configured inside my SCM. This eases the burden of documenting what must be executed in order to have a fully running application. It also helps deploying the application to the production- or staging environment since foreman supports exporting to process monitoring tools like upstart.

Today I want to share a new export feature which was recently added to foreman: supervisor. I’m going to walk through a sample Ruby on Rails project configuration consisting of unicorn and resque.

#1 production environment & Procfile

I like to keep a separate Procfile for each environment which allows me to tweak it if needed without breaking foreman for a different environment. Thus my foreman Procfile is called Procfile.production for the production environment.

# Procfile.production
unicorn: /home/app-user/.rvm/bin/app_bundle exec unicorn -c config/unicorn.rb -E production
worker: /home/app-user/.rvm/bin/app_bundle exec rake environment resque:work

Also following the foreman documentation I have the environment used for export in a separate file, called .env.

# .env
RAILS_ENV=production
VERBOSE=0
QUEUE=*

#2 RVM setup

You might have noticed that I’m not calling bundle exec to start rake or unicorn, but instead I’m using app_bundle exec. app_bundle is a RVM wrapper script which helps me loading the correct version of Ruby as well as the correct gemset. You can create that wrapper by executing the following command:

rvm wrapper 1.9.3-p125 app bundle

If you are using an RVM user installation the script will be placed in /home/app-user/.rvm/bin, executing

which app_bundle

will tell you the correct path.

#3 foreman export

You can now export your processes for supervisord by issueing the following command:

foreman export supervisord /etc/supervisor/conf.d -a app -u app-user \
  -l /home/app-user/shared/log -f /home/app-user/current/Procfile.production -c worker=2,unicorn=1

This will export two instances of the worker process, and one for unicorn. The resulting supervisord configuration should look like this:

  [program:app-unicorn]
  command=/home/app-user/.rvm/bin/app_bundle exec unicorn -c config/unicorn.rb -E production
  autostart=true
  autorestart=true
  stopsignal=QUIT
  stdout_logfile=/home/app-user/shared/log/unicorn-1-out.log
  stderr_logfile=/home/app-user/shared/log/unicorn-1-err.log
  user=app-user
  directory=/home/app-user/current
  environment=PORT=5000,VERBOSE=0,QUEUE=*,RAILS_ENV=production

  [program:app-worker-1]
  command=/home/app-user/.rvm/bin/app_bundle exec rake environment resque:work
  autostart=true
  autorestart=true
  stopsignal=QUIT
  stdout_logfile=/home/app-user/shared/log/worker-1-out.log
  stderr_logfile=/home/app-user/shared/log/worker-1-err.log
  user=app-user
  directory=/home/app-user/current
  environment=PORT=5101,VERBOSE=0,QUEUE=*,RAILS_ENV=production

  [program:app-worker-2]
  command=/home/app-user/.rvm/bin/app_bundle exec rake environment resque:work
  autostart=true
  autorestart=true
  stopsignal=QUIT
  stdout_logfile=/home/app-user/shared/log/worker-2-out.log
  stderr_logfile=/home/app-user/shared/log/worker-2-err.log
  user=app-user
  directory=/home/app-user/current
  environment=PORT=5102,VERBOSE=0,QUEUE=*,RAILS_ENV=production

  [group:app]
  programs=app-unicorn,app-worker-1,app-worker-2

#4 restarting supervisord

You can now have supervisor pick up the new configuration using

sudo supervisorctl reread
sudo supervisorctl update

If you want to know if your app works as expected calling

sudo supervisorctl

will give you additional informations about your processes.

#5 Deployment

When deploying your application you will want to restart all processes associated with your app. Running

sudo supervisorctl restart app:*

will do just that.

finishing words

  • Supervisord support is currently only available in the edge version of the gem. No new version has been made available by now.
  • I’m assuming you are deploying your app using a directory structure similar to that which either Capistrano or Mina creates for you.
  • Your production .env file should not be added to SCM. It should be copied into your application directory upon deployment.

Happy hacking!

© Raphael Randschau 2010 - 2022 | Impressum