Using foreman and supervisord for process monitoring

written by Raphael

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 ror 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 capistrano 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!


handlebars routes assets has been renamed!

written by Raphael

I renamed my Rails asset-pipeline routing integration gem to asset_pipeline_routes, after merging changes from @ubermajestix. You can find it on https://github.com/nicolai86/assetpipelineroutes or https://rubygems.org/gems/assetpipelineroutes.

Besides renaming the gem I also took my time to add some small changes:

  • asset_pipeline_routes requires Rails v 3.2.0 or greater
  • all generated methods now take a parameter which is used to generate the resulting route.

    E.g. given resources :users in your routes.rb

    # application.js.erb
    <%= r.edit_user_path %> // => yields '/users/{{ site.lcb }}{{ site.lcb }}id{{ site.rcb }}{{ site.rcb }}/edit'
    <%= r.edit_user_path '\d+' %> // => yields '/users/\d+/edit'
    
  • besides the regular _path methods asset_pipeline_routes now also generates _methods which return anonymous JavaScript functions to generate the correct routes on the client-side:

    E.g. given resources :users in your routes.rb

    # application.js.erb
    var editUserPath = <%= r.edit_user_method %>; // => yields an anonymous function
    alert(editUserPath(42)); // => alerts '/users/42/edit'
    

Happy hacking!


Everybody! Merry Christmas 2011!

written by Raphael

So, it's been more than a year since I started this blog. And it's been a really nice year for me! But lets start at the beginning:

Merry Christmas everyone! I really hope you can enjoy this years X-mas.

Now, what happened last year? Here's a short recap, in no particular order:

  • Since September 1st I'm employed at Weluse GmbH. The last three months have been really nice and I really enjoy working there. Interesting projects, nice co-workers and a good atmosphere. I'm looking forward to 2012.

  • On Mai 15th I moved in with my girlfriend Katharina. We're both growing on our relationship - so it's a really good one and an intense at that as well.

  • Katharina and I are officially engaged on December 23rd. That's 23.12.11 people! How cool is that? And easy to remember as well! ;)

  • ICS Festival Service GmbH hired me earlier this year to continue my work on the Festivalmanager Software I developed during my time at Empuxa GmbH. We've pretty much extended every part of the system and are looking into another round of changes for 2012. Great news, and plenty of fun as well.

  • Since I started working at Weluse GmbH I got a chance to work on an iPhone/ Android App using Appcelerators Titanium Studio. While the iPhone version worked out okay the Android version didn't. So this year's advice: go native-native and avoid Titanium Studio 4 mobile.

It's been an interesting year after all. Next up: 2012. Guess it can just get better!