Lighttpd SSL Configuration Best Practices

1. Enable SSL Engine

Load mod_openssl and turn SSL on for each listening socket:

server.modules += ( "mod_openssl" )

$SERVER["socket"] == "0.0.0.0:443" {
  ssl.engine = "enable"
}
$SERVER["socket"] == "[::]:443" {
  ssl.engine = "enable"
}

2. Provide a Default Certificate

For each socket block, you must set ssl.pemfile and ssl.privkey at the same level as ssl.engine. Lighttpd 1.4.x will refuse to start otherwise.

$SERVER["socket"] == "0.0.0.0:443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/letsencrypt/live/example.com/fullchain.pem"
  ssl.privkey = "/etc/letsencrypt/live/example.com/privkey.pem"
}

3. Host-Based Certificate Overrides (SNI)

To serve multiple certificates under one socket, nest $HTTP["host"] blocks inside the socket, overriding the defaults per hostname:

$SERVER["socket"] == ":443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/letsencrypt/live/default/fullchain.pem"
  ssl.privkey = "/etc/letsencrypt/live/default/privkey.pem"

  $HTTP["host"] == "site1.example.com" {
    ssl.pemfile = "/etc/letsencrypt/live/site1/fullchain.pem"
    ssl.privkey = "/etc/letsencrypt/live/site1/privkey.pem"
  }
  $HTTP["host"] == "site2.example.com" {
    ssl.pemfile = "/etc/letsencrypt/live/site2/fullchain.pem"
    ssl.privkey = "/etc/letsencrypt/live/site2/privkey.pem"
  }
}

4. IPv4 & IPv6 Binding

5. Testing & Validation

6. Notes on Lighttpd Versions

7. Redirect HTTP to HTTPS

$HTTP["scheme"] == "http" {
  url.redirect = ( ".*" => "https://%0$0" )
}

By following these guidelines—setting a default certificate, nesting host-based overrides, and explicitly binding both IPv4 and IPv6 sockets—you can reliably serve multiple TLS certificates with Lighttpd 1.4.x and ensure your HTTPS sites stay online.