zargony.com

#![desc = "Random thoughts of a software engineer"]

Migrating from Apache to Lighttpd with name-based virtual hosts and SSL

This weekend, I switched our webserver from Apache 2.2 using name-based virtual hosts to Lighttpd 1.4.18. This was something I wanted to do for month now, since Lighttpd seems to be much easier to configure and maintain when it comes to name-based virtual hosts, FastCGI applications (like Ruby on Rails) and SSL. Since Lighttpd gains more and more popularity, there were almost no problems migrating from Apache to Lighttpd. Especially name-based virtual hosts are easier to configure in Lighttpd.

On our server, we had an Apache configuration with name-based virtual hosts and SSL which was a hell to maintain in the past. Usually you cannot run name-based virtual hosts with SSL, because the SSL handshake (which exchanges the certificate) is run before the "Host" header is transferred (which is needed by the webserver to determine which name-based virtual host a request goes to). So you usually need to assign a seperate IP vor every virtual host that should be accessible via HTTPS. This is the reason why every documentation tells you to use ip-based virtual hosts with SSL.

However, in my case every vhosts is a subdomain of a common domain and the server has a wildcard-certificate (e.g. issued to *.mydomain.com). This doesn't seem to be a very common configuration (at least I didn't find many people writing about this), but in theory it should work fine since the certificate is all the same for every vhost. However, Apache always kept logging warnings that multiple ssl-enabled vhosts sharing one IP are bad to have. Even though annoying, those warning can be ignored and it still works...

...at least as long as you don't try to configure a wildcard vhost. With plain HTTP, it works well as long as you carefully watch the order in which you define your virtual hosts:

  • wiki.mydomain.com
  • trac.mydomain.com
  • *.mydomain.com

With HTTPS, this becomes a nightmare. Not only Apache reporting lots of warnings about multiple vhosts using SSL on the same IP, but also the order you need to define vhosts seem to be reversed... or sometimes not working at all. I guess the whole configuration is unsupported by apache.

Lighttpd to the rescue. Using conditional configuration statements in lighttpd.conf, the above configuration runs without any problems:

$SERVER["socket"] == "0.0.0.0:443" {
  ssl.engine = "enable"
  ssl.pemfile = ...
  ssl.ca-file = ...
  $HTTP["host"] == "wiki.mydomain.com" {
    server.name = "wiki.mydomain.com"
    server.document-root = ...
    accesslog.filename = ...
    ...
  }
  else $HTTP["host"] == "trac.mydomain.com" {
    server.name = "trac.mydomain.com"
    server.document-root = ...
    accesslog.filename = ...
    ...
}
else {
  server.name = "mydomain.com"
  server.document-root = ...
  accesslog.filename = ...
  ...
  }
}

I noticed just one strange thing happening while playing around with conditionals in lighttpd.conf (which almost drove my crazy friday evening): Gracefully restarting lighttpd sometimes seem to mess up the configuration parser. Sometimes after changing the confguration and doing a graceful restart (/etc/init.d/lighttpd graceful), I was presented with strange configuration errors, random 500 errors and crashing FastCGI processes (php-cgi). It took me some time to find out that all problems were gone after normally restarting lighttpd. I suppose the graceful restart isn't perfect yet.

For now, I'm absolutely satisfied with lighttpd -- as promised, it's fast and lightweight. I wonder, how I'll think about it in a few weeks and if I'll be ever hit by memory problems or random crashes like some high-traffic site admins were reporting in the past.