Monthly Archives: October 2010

Running Unicorn under supervise/daemontools

I’m running a Rails3 app under daemontools, this is how I did it.

First, install then start daemontools and Unicorn. This is left as an exercise for the reader, it was easy under CentOS 5. You should end up with a /service directory on your server.

Run “mkdir /service/my_service_name && cd /service/my_service_name && ls”. If you have the right processes running you should have a “supervise” subdirectory automatically created for you under your new directory.

You should be in the “/service/my_service_name” directory. In order to get anything to run you need to create a “run” script. Here’s mine, you can copy and modify it for your own use. If you’re running Unicorn and you improve the script I’d appreciate feedback in the comments:

#!/bin/sh
cd /home/www/foo/current && unicorn_rails -E staging -c /home/www/foo/shared/config/unicorn.conf

Make sure the script is executable. If you have done everything right you should have a Unicorn process running. You should see something similar to this in the output of “ps auxww -H”:

If that’s not the sort of thing you see, check the logs. Lastly I added this cap snippet to kill the process on deploy and let supervise handle re-spawning it:

Done!

Why daemontools?

There is some propaganda on the daemontools site, but I used it because it’s quick to get going and in my experience reliable. I use monit a lot at Engine Yard, but there are no recent monit packages easily available for CentOS that I have found. One drawback is that you don’t get any of the resource monitoring that monit provides, such as http checks, memory checks etc. You’d have to implement this yourself, but in this instance that’s the tradeoff you make for simplicity.

CentOS 5 update:

If you get an error that looks like this:

Follow these instructions to fix the issue:

Simple http ping program in Ruby

Just a little http ping program I wrote to check request latency during my testing for zero-downtime rails deploys with Unicorn.

Example:

pinky:~ will$ ruby httping.rb willj.net
200 :   0.000000   0.000000   0.000000 (  0.761449)
200 :   0.010000   0.000000   0.010000 (  0.535888)
200 :   0.000000   0.010000   0.010000 (  0.800904)
200 :   0.000000   0.000000   0.000000 (  0.530763)
200 :   0.000000   0.000000   0.000000 (  0.811362)
200 :   0.000000   0.000000   0.000000 (  0.557995)
200 :   0.000000   0.010000   0.010000 (  0.774484)

Tagged

Really Small Monitor

I recently got an iPad to ease my imminent travels, the (alleged) 10 hours of video and the ability to store a load of books will make the long plane journeys and layovers much more tolerable. The other big benefit is that when I get to where I am going I will be able to use it as a second monitor for my laptop.

Caius had previously suggested AirDisplay, an app that as it’s name suggests lets you use it as a wireless display for your computer (Mac and Windows) as long as they are both on the same wireless network. I bought it almost as soon as I got my iPad and tried it out in a coffee-shop. Throughout the day I used it for terminals and my Limechat IRC client and it worked well, staying connected almost continuously. The display updates fast enough for those simple uses, but stutters on web-page scrolling (though it’s still usable) and would be useless for video. Here’s a picture of it with a Textmate window dragged onto it:

AirDisplay is definitely worth a go if you travel with a laptop and like to have a second monitor. It seems to be a bit fussy with wireless networks though, I had no problems with a mifi wireless network and my 802.11n home network, but it wasn’t happy with my dad’s wireless network, it took ages to get it to connect and it got disconnected a fair few times. It also works on an iPhone if you’re really desperate:

Tagged ,

Unicorn and bundler issue

I am using unicorn with a rails3 app that uses bundler and I hit a weird error when trying to start a server:

`rescue in load_spec_files': git://github.com/odorcicd/authlogic.git (at rails3) is not checked out. Please run `bundle install` (Bundler::GitError)

The background to this is that I am starting unicorn_rails as root then dropping privs in the after_fork block, this is the relevant section from my unicorn.conf file:

after_fork do |server, worker|
  # …
  uid, gid = Process.euid, Process.egid
  user, group = 'will', 'will'
  target_uid = Etc.getpwnam(user).uid
  target_gid = Etc.getgrnam(group).gid
  worker.tmp.chown(target_uid, target_gid)

  if uid != target_uid || gid != target_gid
    Process.initgroups(user, target_gid)
    Process::GID.change_privilege(target_gid)
    Process::UID.change_privilege(target_uid)
  end
end

This is basically the same as the GitHub unicorn config.

Back to the problem. It works fine for all the standard rubygems.org gems, but was failing on the dependencies I had specified as ‘:git’ deps, for instance authlogic:

gem 'authlogic', :git => 'git://github.com/odorcicd/authlogic.git', :branch => 'rails3'

I checked where these gem/git dependencies were being stored and saw the problem:

[will@server current]$ bundle show activerecord
/usr/local/lib/ruby/gems/1.9.1/gems/activerecord-3.0.0

[will@server current]$ bundle show authlogic
/home/will/.bundler/ruby/1.9.1/authlogic-a087ad0

The :git dependencies were being bundled to a subdirectory of my home dir (the same user that does the deploy, and therefore the initial bundle install. The unicorn_rails process starts as root and has already run Bundler.setup before it forks, so Bundler.setup gets run as root, and the root user has no idea where the :git dependencies are, hence the error.

I solved this by adding a call to Bundler.setup from within the unicorn.conf after_fork block:

after_fork do |server, worker|
  Bundler.setup
  # …
  uid, gid = Process.euid, Process.egid
  user, group = 'will', 'will'
  target_uid = Etc.getpwnam(user).uid
  target_gid = Etc.getgrnam(group).gid
  worker.tmp.chown(target_uid, target_gid)

  if uid != target_uid || gid != target_gid
    Process.initgroups(user, target_gid)
    Process::GID.change_privilege(target_gid)
    Process::UID.change_privilege(target_uid)
  end
end

It seems to work fine, better solutions welcome!

Tagged , ,

Fairtrade music?

My friend @sudara is a musician and is interested in changing ideas about how music can and should be created and distributed*. He has started the site Ramen Music where you can sign up for issues of new unsigned hand-picked quality music. Artists get paid fairly (~75% of the money ramen music takes, 100% for the first year).

Sharing is encouraged so here is my first issue (I have a paid subscription). With a paid account you can download high-bitrate non-DRM’ed MP3s of all the music in an issue, but he’s giving away access to the first issue to people who want it:

If anyone else wants a free taste of Ramen Music #01, follow us and we’ll DM you.

I’d be interested to know people’s thoughts and opinions on the idea, the music and the state of the Music industry in general.

* The state of the Music industry is a debate I’ve had with a bunch of people in the past, and it seems independent and new musicians are not served well by the current models.

Tagged ,
Follow

Get every new post delivered to your Inbox.