Mixing it up with lighttpd and Sinatra

If you’re looking for a super-fast, standards-compliant httpd server, I can wholeheartedly recommend lighttpd (lighty to its friends). Well known as the engine behind YouTube and Wikipedia, and with a very low memory footprint, it’s a super piece of software, and has been running our website for a couple of years now.

When I decided it was about time I got round to getting some content on http://agilesysadmin.net, I considered the obvious choices - Wordpress or Drupal, but felt they were both a bit heavyweight for my liking. Instead I turned to Nesta - the lightweight CMS written by Graham Ashton of Effectif, a friend and former colleague of mine at Wordtracker. I love its simplicity, and its implementation of Mark Nunney’s SEO-friendly website building guidelines.

Nesta runs on the fashionable Sinatra web framework. Now, I usually tend to run Passenger for Rails websites, so that seemed like an obvious choice, but I didn’t want to stop running lighttpd. I did, however, want to get the Sinatra app up and running quickly. Here’s how to do it:

  1. Install rubygems from backports

    $ echo “deb http://www.backports.org/debian lenny-backports main contrib non-free” » /etc/apt/sources.lst

    $ apt-get install debian-backports-keyring

    $ apt-get update

    $ apt-get -t lenny-backports install rubygems

  2. Install some build tools

    $ apt-get install g++ make ruby1.8-dev rake

  3. Install the gems (without the documentation on the server)

$ gem install –no-rdoc –no-ri sinatra rack thin

There are a few other gems needed for the application, but for the purposes of getting a Sinatra app up and running, this should suffice.

A bit about rack

One of the better developments in the Ruby web world in the last year or so is Rack. Rack is similar to Python’s WSGI - it presents an api which enables web applications to be run by a range of webservers in an agnostic manner. This provides a minimal interface between webservers that support Ruby and Ruby frameworks. In order to use Rack, you need a simple file called a ‘rackup’ file. Conventionally these are called config.ru. Nesta ships with one:

require "rubygems"
require "sinatra"
require "app"

run Sinatra::Application

Configure lighttpd

We’re going to use lighttpd to proxy http requests to a backend server on a high port.

First, ensure mod_proxy is enabled:

server.modules              = (
       	"mod_access",
       	"mod_alias",
       	"mod_accesslog",
       	"mod_compress",
       	"mod_proxy",
		)

Then create a virtualhost in lighttpd. We’re using the ‘fair’ algorithm, which balances requests evenly between the servers listed. In our case we’re specifying two - one on port 3000 and one on 3001.

$HTTP["host"] =~ "(www\.)?agilesysadmin\.net"  {
    	proxy.balance = "fair"
    	proxy.server =  ("/" =>
                            	(
                                    	( "host" => "127.0.0.1", "port" => 3000 ),
                                    	( "host" => "127.0.0.1", "port" => 3001 )
                            			)
                    					)
			}

A bit about thin

Now we just need to start up the application. There is an embarras de richesses when it comes to Ruby webservers, but I like Thin - it combines the Mongrel parser, plus the highly scalable Event Machine network I/O library. I’ve not yet tried Unicorn, but from reading about Github’s scaling exercise, it could well be worth a look. However, of the Ruby servers I’ve tried, Thin seems to the fastest.

All we need to do is start it up, specifying the number of servers, and the path to the rackup file:

$ thin -s 2 -R config.ru start

And there you have it - browse to your new virtual host, and enjoy your Sinatra app.