Ruby on Rails
Lighttpd

Why Lighttpd

Lighttpd is a fast webserver that is very similar in speed to Apache 2.0 MPM-Worker on Linux. This means it is substantially faster than both Apache 1.x and Apache 2.0 MPM-Prefork.

Lighttpd is easy to configure, supports fastcgi/scgi well, and can handle heavy loads with little CPU usage. It is available for Unix-like environments (*BSD, Linux, OS X, Cygwin for Windows etc.) Kevin Worthington has been kind enough to provide an easily installable build for Windows (native Win32 binary, no Cygwin needed).

Step 0: Lighttpd and spawn-fcgi

Get lighttpd and spawn-fcgi (included by default in lighttpd now) from the Lighttpd site, compile and install, or use your operating system’s package manager to do the work if possible. Make sure you have pcre and pcre-devel installed as well (under some distros these will be called libpcre3 libpcre3-dev, respectively).

Manually install ruby-fcgi as the gem doesn’t work (in irb, try: require ’fcgi’) — you may need to install FastCGI first.

Debian and Ubuntu Linux users can use the “libfcgi-ruby1.8” package (apt-get install libfcgi-ruby1.8).

Step 1: Set up modules within lighttpd configuration

Make sure that server.modules includes atleast mod_fastcgi, mod_rewrite and mod_redirect:

server.modules = ("mod_rewrite","mod_redirect","mod_fastcgi")

Step 2: Set up your document root

server.document-root = "/path/to/rails/public"

Step 3: Set it up to automatically spawn the fcgi processes.

# old way
#fastcgi.server = (".fcgi" => ( "railsapp" => ("socket" => "/path/to/#rails/socket")))

# new way.  include as many sockets as you want.  I use 5.
fastcgi.server =  (".fcgi" => ( "railsapp" => 
  ( "min-procs" => 1,
    "max-procs" => 5,
    "socket" => "/tmp/ruby-railsapp.fastcgi",
    "bin-path" => "/path/to/dispatch.fastcgi"
  )
))

You can also use spawn-fcgi to create a socket, then just point the socket. But it’s easier to let the main lighttpd program do it for you.

(Could anyone add some info on “bin-path”, please? directory “/path/to/dispatch.fastcgi” should point to something sensible. For instance?.. Also, is “railsapp” a kind of reserved word or it is an example of the rubyonrails application and may vary in each case?)

(Well, you see the dispatch.fcgi is a file that is containt in ruby-on-rails applications. Let’s say you want to install Mephisto RoR blog engine, when you look at mephisto folder there is a public/ dir which contains the dispatch.fcgi file.)

RailsApp is optional and is referred to the name of the application. If you don’t want that, you can avoid it without issues

Step 3a: Set up multiple domain names w/fastcgi & conditionals

If you want to use multiple domains, for each domain name you want to set up, you will need to set up conditionals:

$HTTP["host"] =~ "\.railsapp\.com" {
fastcgi.server = ( ".fcgi" => ( "railsapp" => ("socket" => "/path/to/rails/railsapp.socket"))) }

$HTTP["host"] =~ "\.railsapp2\.com" {
fastcgi.server = ( ".fcgi" => ( "railsapp2" => ("socket" => "/path/to/rails/railsapp2.socket"))) }

Step 4: Set up the 404 handler

Since rails 0.10, rewrite rules have become obsolete in favour of Routes. Instead, you can use the 404 handler:

server.indexfiles = ( "index.html" )
server.error-handler-404 = "/dispatch.fcgi"

This has the advantage of allowing you to serve files from the public/ directory, but everything that isn’t a file is given to rails, which uses the routes to figure out whatever URL you give it. Sure beats the heck out of those complicated rewrite rules, and you’ll never have to see another error message caused by Rails not being able to find the Image.jpgController…

Step 4 (for rails older than 0.10 only): Set up rewrites

This is the equivalent of the FCGI part of the .htaccess file in the normal install. These have been updated to include data in the query-string (/front/index?my_arg=1).

url.redirect = ("^/$" => "http://yoursite/defaultcontroller/defaultaction")


url.rewrite = ( 
  "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9%]+)\??([\-_a-zA-Z0-9=&%]*)$" =>
  "/dispatch.fcgi?controller=$1&action=$2&id=$3&$4",
  "^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$" =>
  "/dispatch.fcgi?controller=$1&action=$2&$3",
  "^/([\-_a-zA-Z0-9]+)/?\??([\-_a-zA-Z0-9=&%]*)$" => "/dispatch.fcgi?controller=$1&action=index&$2"
)

Step 4a: Set up default redirects per application

If you want to have your application be the home page, and you will have different applications for different domains being the home page, you will modify your conditional (above) to contain the url.redirect line:

$HTTP["host"] =~ "\.railsapp\.com"  {
fastcgi.server = ( ".fcgi" => ( "railsapp" => ("socket" => "/path/to/rails/railsapp.socket")))
url.redirect = ( "^/$" => "/weblog" )}

Step 5: launch lighttpd

Run it the usual way — either run lighttpd, or use the startup mechanism from your operating system.

Miscellaneous

Running a production rails app – If you want to make model/controller changes effective without restarting lighttpd (which can take a while if you have several fcgi apps) you can do something like:


ps aux | grep myappname | egrep -v grep | awk '{print $2}' | xargs kill -9

This kills all the fcgi processes for your app. They are then respawned when access requests are made.

Kill -9 should almost certainly not be used (see http://sial.org/howto/shell/kill-9/ ). Also, most systems probably have a pkill(1) so pkill -SIGNAL myappname will suffice.

Troubleshooting

If you get pcre errors like this

2004-10-12 21:28:39: (mod_rewrite.c.235) 
pcre-compile failed for ^/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)/([\-_a-zA-Z0-9]+)$ 

Make sure you install the pcre-devel library THEN compile lighttpd.

See Also

Lighttpd Rails Script