Security headers for lighttpd

TL;DR To configure your lighttpd webserver to use security headers that will harden your website against common hacking attacks, add the section below to your config file (typically /etc/lighttpd/lighttpd.conf), restart the webserver, and you're good to go.
server.modules += ("mod_setenv") 
 
$HTTP["scheme"] == "https" { 
  setenv.add-response-header = ( 
    "Referrer-Policy" => "same-origin", 
    "Strict-Transport-Security" => "max-age=31536000", 
    "Content-Security-Policy" => "default-src 'self'", 
    "X-Frame-Options" => "DENY", 
    "X-Content-Type-Options" => "nosniff", 
    "Permissions-Policy" => "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()", 
    "X-Xss-Protection" => "1; mode=block", 
    "Server" => "my webserver", 
  ) 
} 

troubleshooting the setup

Some problems you may run into:

why do I want these headers?

The headers listed above help prevent common hack attempts by allowing less and revealing less. Most headers add an extra layer of defense, making it harder to exploit mistakes in the website running on your webserver. For example, when an attacker manages to inject javascript or other malicious content in your website, these measures will help limit the resulting damage. To see in what shape you website is, you can enter the url on the securityheaders.com website and will get a rating together with some hints how to improve. I'll dive into the different headers in more detail below.

Referrer-Policy

The Referrer-Policy header controls how much information the browser will send in the referer header for requests made from your site. Note that the actual request header is incorrectly spelled "referer", while this header and its values use the correct spelling of the word. Good options are no-referrer (omits the header) or same-origin (only include for requests to the same site). Restricting the referer headers prevents accidentally leaking any sensitive data in the originating url.

Strict-Transport-Security

The Strict-Transport-Security or HSTS header tells your browser to always use https when connecting to your website. This prevents certain hacks where the attacker tries to trick visitors into using http to connect to the website, making the traffic susceptible to snooping. The max-age parameter is the time the browser should remember this, in second. For a year, use 31536000.

Content-Security-Policy

The Content-Security-Policy or CSP header tells the browser which sources are okay to load content from. This can stop maliciously injected content from being fetched by the browser. Can be specified per resource type.

X-Frame-Options

Whether this webpage can be put in a frame. Turning this off helps prevent clickjacking for your site.

X-Content-Type-Options

This modifies the browsers behavior to "guesstimate" the type of content it is being served. This can be abused in some hacking scenarios, so better turn it off by setting it to "nosniff", where no assumptions are made and the only the Content-type header is respected.

Permissions-Policy

This header limits the type of "special" permissions your website will try to use. For example, if you know your website should never ask for "geolocation" or "camera", you can turn it off. This way any maliciously injected code won't succeed in gaining such privileges. Only problem is that there's no "deny all" option, so you have to list every possible option, making it kind of verbose. Also, you have to revisit from time to time, as new permission types will keep being added. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

X-Xss-Protection

This header is sort of dubious, as it is not part of the http standard. Some (older) browsers do some cross site scripting mitigation when the header is set, but no guarantees. MDN even recommends not using it, unless you expect to be serving older browsers, in which case you should set it to 1; mode=block".

Server

The server header may reveal detailed information on the exact type of webserver you are using, e.g. Apache/2.4.1 (Unix). Lighttpd also does this by default. This is not so great, as it makes it easier for attackers to abuse known problems in the specific webserver you are running, so it's best to either disable the header, or set it to something generic, like my webserver


related blogs: