Migrating from Apache to LigHTTPD

After running Apache 2 as the main web server for maybe three or four years I have now made the switch to LigHTTPD, or Lighty. This is due to several reasons, but mainly due to problems with running Ruby on Rails applications behind Apache 2.

There are several ways of running a Rails application. One can use WEBRick, the server usually used during development. It’s all ruby and needs no configuration. Though it’s not that fast, or have heaps of features.
One could run Rails behind Apache with CGI. With this approach you get a good web server, with heaps of features, but CGI isn’t all that good. Actually, the whole Ruby environment will be reloaded in every page view, or rather, every request. This is a real drag on performance and memory use and not preferred.
A Rails application can be run with mod_fastcgi, but the fastcgi module for Apache 2 has not been in active development since late 2003 (afaik) and there are a few known issues that according to the tale have caused some backwards migrations to Apache 1.3.
One can use any other web server capable of CGI or fast CGI, but when it comes to the usual Linux box, it has got Apache running, if any server.

There are also other things to consider. In my case I have a lot of old PHP pages wich I do not want to rewrite. I also had a TurboGears application running behind Apache 2. This application was actually just a CherryPy webserver on a different port wit a proxy from Apache.

So, what I wanted was a way of serving PHP, Ruby on Rails and TurboGears while serving some of these pages over HTTPS. Apache 2 could have done this, of course, but there was issues. Number one, Ubuntu does not ship the usual mod_fastcgi, so I had no nice instructions on how to deploy Rails with my server. The application was ridiculously slow with Apache 2 + CGI so that was not really a choice. I don’t know why, but I have always had bad feelings about running the proxy towards CherryPy. And last, Apache is good, but it’s a beast. It’s huge, and complex, and well, after three or four years I don’t know half of what Apache can do for me. So I started looking at what LigHTTPD could do for me and actually found everything that I need, including a nice blog post about TG and Lighty.

So what did I do? I tried my old friend apt-get install lighttpd but it failed since it was not included in the Hoary Hedgehog. So instead I grabbed the sources and created a .deb package for hoary. This package can be downloaded here if anyone would like to use it. I actually just copied an old debian directory into the new sources, updated the changelog and executed dpkg-buildpackage. This left me with a somewhat strange install, which is what you will get by my package, due to the old debian dir not including some parts of the debian patch. The thing was that the config files was laid out kind of like debian does with Apache so that files can be symbolically linked into the enabled dir and included in the configuration. It took me ages to figure out why the config files symlinked to confs-enabled never was read by the server. However, after fetching the debian source package from unstable i was able to extract one script and also a line needed int the main config file for this setup to work. The scripts can however NOT be put where the patch suggests or the server will never be able to execute them. Here we face another problem. Lighty can execute scripts and use the output as parts of it’s configuration. This is actually how the symlinking works. Debian includes a perl script that reads the directory, sorts the array of files and then outputs what’s in them, which is then included in Lightys configuration. But if Lighty fails to execute the scripts it will never tell you since it seems to completely ignore everything written to stderr. After arguing allot with Lighty i finally put the perl scrits in /usr/bin, added the x flag and tried to run it. The way I found out it worked was to output things that Lighty would not like and then get it to not start.

The script can be found here. Also remember to put include_shell "include-conf-enabled.pl" at the end of the main configuration file. What I have done on my setup is to also create a sites-enabled directory and duplicated the script, just changing which directory to read to keep trac of my v-hosts.

So, with the config parts included at last it was time to begin the migration. I started Lighty on port 3000 and started including a feature at the time, starting with PHP. First of all i created a config file for including the mod_fastcgi, making sure that this is done before PHP (since we will run php with fast_cgi) by calling it 05-fastcgi.conf. The reason it’s not 01 or 00 is that mod_auth must be loaded before mod_fastcgi if you shall be able to use mod_auth for those applications.

01-mod-auth.conf:
server.modules += ( "mod_auth" )
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/path/to/passwords/htpasswd"
auth.backend.plain.groupfile = "/path/to/passwords/groups"
I have not tested if the groups work yet.

05-fastcgi.conf:
server.modules += ( "mod_fastcgi" )

11-php.conf:
fastcgi.server = ( ".php" => (
( "bin-path" => "/usr/bin/php-cgi",
"socket" => "/tmp/php.socket",
"max-procs" => 2,
"bin-environment" => (
"PHP_FCGI_CHILDREN" => "16",
"PHP_FCGI_MAX_REQUESTS" => "10000" ),
"bin-copy-environment" => ( "PATH", "SHELL", "USER" ),
"broken-scriptfilename" => "enable" )
)
)

On ubuntu I also had to do a apt-get install php4-cgi, or 5 or 3 or whatever. After that I found out I had to edit the php.ini found at /etc/php4/cgi/php.ini and add all the modules that I could find in /etc/php4/apache2/php.ini.
This was added to the cgi php.ini:
extension=mysql.so
extension=mhash.so
extension=imap.so
extension=gd.so
extension=mcrypt.so
extension=domxml.so

Also i had to uncomment cgi.fix_pathinfo=1 to be able to get IMP running. Otherwise it makes a mess of the paths.

To get WordPress to handle permalinks (it usually uses Apaches mod_rewrite + htaccess) i had to add this to the v-host running the blog:
$HTTP["url"] =~ "^/blog/" {
server.error-handler-404 = "/blog/index.php?error=404"
}

Please notice that the blog is on a virtual domain but under the url /blog/
By the way, i do not use mod_simple-vhost, I only use conditional v-hosts, seems just as easy, and the nesting is awesome.

By this time PHP was up and runnig with the same functionality as with the old Apache 2, YAY.

To be able to run Rails on fcgi Ruby needs the fast_cgi module. To be able to build it in Ruby you need to have libfcgi(-dev) installed on your machine. This is a simple apt-get in Ubuntu. fast_cgi will then be installed trough Ruby Gems, or apt-get. I prefer Gems, since my Hedgehog is rather old.

apt-get install libfcgi-dev
gem install fcgi

Now we need a config file to include in Lighty, XX-whatever.conf: $HTTP["host"] == "rails.example.com" {
server.error-handler-404 = "/dispatch.fcgi"
server.errorlog = "/path/to/appliction/log/server.log"
server.document-root = "/path/to/appliction/public/"
fastcgi.server += (
".fcgi" => (
"localhost" => (
"min-procs" => 10,
"max-procs" => 10,
"socket" => "/tmp/rails.fcgi.socket",
"bin-path" => "/path/to/applictian/public/dispatch.fcgi",
"bin-environment" => ( "RAILS_ENV" => "production" ) # if you want to
)
)
)
}

Restart Lighty and you have a shiny Rails application running super fast!!!

Time for Turbo Gears!!
Now, TG will always run with CherryPy, but you can do this in different ways. I choose the hard way, the second on this page. Just do as the guide tells you except do NOT add mod_staticfile. By adding it PHP stopped working. The Python script they are writing could either be rewritten using this recipe or started with start-stop-daemon to get a background process.

This pretty much concludes the story of migrating from Apache 2 to LigHTTPD, I can now run TurboGears (www.sunkhakgbg.info) and PHP on Lighty, and it feels much faster than Apache to.

Leave a Reply