Wandering Thoughts archives


Some lighttpd bits

Lighttpd is a popular lightweight web server I've been experimenting with; in the process, I've wound up stumbling over various things that I should write down this time around (I played around with lighttpd about a year ago but then forgot a bunch of this stuff).

  • unlike Apache, lighttpd's error log is global; there's only one, not one per virtual host. If you accidentally set server.errorlog multiple times (perhaps in virtual host setups), only the last one gets any messages.

    (Not being able to set per vhost error logs is relatively harmless, because much less winds up in lighttpd's than in Apache's.)

  • the way you set the character set for HTML pages and so on is to change the MIME type assignments to append a '; charset=<whatever>' to the end of various MIME type entries. Unfortunately, you must do this by changing the main mimetype.assign table (or repeating it wholesale); you cannot do it with something like:
    mimetype.assign += (".html" => "text/html; charset=UTF-8")

    (What happens with += is that the .html entries add to each other instead of your version replacing the old one, so you generate Content-Type headers that look like 'text/html, text/html; charset=UTF-8'. This generally ends in tears.)

  • most matching of URLs is purely textual; for example, if you just match:
    alias.url += ( "/cgi-bin" => ...)
    you will block access to '/cgi-bin2-foobar' and the like. In this case you want to use '/cgi-bin/' (with the slash on the end), and in general the magic regexp to use is '^/foo($|/)', which matches /foo only when it is a complete path component.

I have to say that lighttpd's configuration stuff can be a bit scary sometimes; once you start using its conditional things, it's practically a programming language. I'm more used to configuration files that don't have to be partially interpreted on every request, and thus where you can clearly see what settings are in effect.

(Lighttpd allows you to set core server configuration variables based on matching against various bits of the HTTP header. For example, the lighttpd way of doing simple virtual hosts is to check the HTTP Host: header and set completely different document roots, log files, CGI configurations, and so on.)

It is kind of a pity that you can't take lighttpd configuration to the logical next step and write macros. I suppose you can get pretty close with include files, but you can't easily pass them arguments.

Sidebar: sending a URL hierarchy to a CGI

There's at least two ways of sending an URL hierarchy to a CGI program in lighttpd; the cgi-bin way and the direct way. The cgi-bin way is to configure yourself a traditional cgi-bin directory area, and then use URL rewriting to point stuff there (ie, the traditional Apache approach transplanted). With your /cgi-bin/ stuff already configured, it looks like this:

url.rewrite-once = ("^/foo($|/.*$)" => "/cgi-bin/foo$1")

The direct way is to send the root URL straight off to an executable without bothering to configure a generic CGI area:

$HTTP["url"] =~ "^/foo($|/)" {
  alias.url = ("/foo" => "/some/where/cgi/foo")
  cgi.assign = ("" => "")

It's safe to stomp all over alias.url and cgi.assign here, since we're only running one thing in the section and thus can't need any other settings they may have. I was pleased to see that setting alias.url to point to a file instead of a directory works fine.

(This sort of thing is where the configuration stuff starts turning into a programming language.)

I personally prefer the direct way, because it leaves less stuff accessible for excessively clever people. Why have an accessible set of /cgi-bin/ URLs if you're not actually using them for anything?

sysadmin/LighttpdBits written at 23:44:02; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.