Lighttpd Web Server

From Elvanör's Technical Wiki
Jump to navigationJump to search

lighttpd is a fast, small web server. It is supposedly lighter than Apache, however it has a lot of features like proxying, url rewriting, virtual hosts and so on.


  • To get PHP working (via cgi), you need this line in lighttpd.conf:
include "mod_fastcgi.conf"
  • As mentionned in the mod_compress documentation, if you use a charset for a filetype (JavaScript), you should use the full mime-type with the charset included, else it won't act on this filetype. See this link.

URL Rewriting

  • URL rewriting does not work inside an HTTP["url"] conditional block.
  • You can use %1, %2 in a url rewriting directive. These correspond to the groups of your HTTP["host"] regular expression. They have nothing to do with the same variables for mod_evhost. Example:
$HTTP["host"] =~ "^(?!(images|css|static|www)\.)([^\s.]+)\.shoopz-local\.net$" {
        url.rewrite-once = ( "/sitemap\.xml" => "/%2-sitemap.xml", "^/(.*)$" => "/shop-engine/$1" )
        server.document-root = "/srv/" + domain + "/static/sitemaps/"

        $HTTP["url"] !~ "^/(.*?)-sitemap\.xml$" {
                proxy.server = ( "" =>
                ( (
                        "host" => "",
                        "port" => 8080
                ) )
  • You can also use %1, %2 in the evhost.path-pattern directive.

Cache Control

  • For this you need to use mod_expire and mod_setenv. Typically, you want to setup the Expires and Cache-Control headers. Example:
setenv.add-response-header = ("Cache-Control" => "public")
expire.url = ("" => "access plus 5 minutes")
$HTTP["host"] =~ "^static" {

expire.url = ("/js/editor/resource/" => "access plus 7 days", "" => "access plus 1 days")

else $HTTP["host"] =~ "^images" {

expire.url = ("/library/" => "access plus 7 days", "" => "access plus 5 minutes")

  • This would enable caching via Cache-Control: public, and configure everything to be strongly cached (without revalidation) for 5 minutes. Specific directories on the static and images host have different settings.

Proxy mode

  • If used as a proxy, lighttpd 1.4.x cannot compress the output of the remote server (via mod_compress). For this you need mode_deflate, only available in 1.5.x.


  • To generate the certificate request, use:
openssl req -new -x509 -keyout server.pem -out server.pem -days 10000 -nodes

To create a wildcard certificate, which is usually what you need, pay attention to the questions asked by the tool. For Common Name (e.g. server FQDN or YOUR name) []:, enter something like *

  • Note that this is enough to generate a self signed certificate; eg, you can simply copy the server.pem file to /etc/lighttpd/certificates/ and start using lighttpd with a self-signed certificate if you're in a test or development environment.
  • Be careful to use the following in /etc/lighttpd/vhosts.d/00_default_vhost.conf, at the beginning of the file:
$SERVER["socket"] == ":443" {
        ssl.engine = "enable"
        ssl.pemfile = "/etc/lighttpd/certificates/server.pem"
  • If you include this snippet inside a virtual host conditional, this won't work! Be very careful!

Obtaining the certificate with StartSSL

  • Generate the certificate request:
openssl req -new -newkey rsa:2048 -nodes -out kameleoon.csr -keyout kameleoon.key
  • Then go to StartSSL interface, ask for a new web server certificate. Skip the first step (since you generated the Certificate Signing Request yourself) and paste the CSR part (kameleoon.csr) into the field in the second step. Note the key that was generated by OpenSSL (kameleoon.key); you will have to paste it into the final .pem file.
  • Fill out the target domain for the certificate. Wildcards are supported, if you have a Class 2 Validation or higher.
  • Once this is done, you can get the private key (kameleoon.key) and the certificate (given by StartSSL) into a server.pem file, and point lighttpd directly to that.

Accepting self-signed certificates in different browsers

  • For Chromium:
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n <certificate nickname> -i <certificate filename>


  • lighttpd-1.4.19 had a bug when no actual content was sent on a HTTP 410 return code (from a proxy). Fixed in 1.4.20.
  • lighttpd-1.4.19 had a bug with URLs containing an url-encoded slash (%2F). It returned a 400 status code. Fixed in 1.4.20.


  • When used as a proxy to Apache, if Apache issues a 301 redirect, lighttpd does not send it to the client right away. It waits until Apache closes the TCP connection. By default this takes 15 seconds so the redirect takes 15 seconds! A workaround is to lower the keep alive timeout of Apache (to 1 second for instance). This affects lighttpd versions until at least 1.4.28.