Skip to content

Enable HSTS in nginx

Severity: mediumApplies to: nginx 1.25+Applies to: nginx 1.30 / 1.31Applies to: freenginx
The fix/etc/nginx/snippets/security-headers.conf
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

Start with a short max-age300 — and raise it once you’re sure. The reasons are in the safety section, and they are the whole point of this page.

A redirect from HTTP to HTTPS still leaves one plaintext request on the wire, and that request is the attack. Someone on the path intercepts it, never lets the redirect through, and proxies the session over plaintext. The user sees a working site and no warning.

HSTS closes it by telling the browser: for the next max-age seconds, never use plaintext for this host — rewrite it to HTTPS before sending anything. After the first successful visit, there is no plaintext request left to intercept.

That first visit is still exposed, which is what preload addresses, at a cost.

Part Meaning
max-age=63072000 Remember for two years. The browser refreshes it on each visit.
includeSubDomains Apply to every subdomain, including ones you forgot.
preload Ship the rule in browsers, so even the first visit is protected.

includeSubDomains is the sharp edge. It applies to hosts you’re not thinking about — legacy.example.com, the intranet box, the vendor’s CNAME. Any of them that cannot do HTTPS becomes unreachable in every browser that has seen your main domain, and there is no way to fix it from that subdomain’s side.

Only add preload if you mean it permanently

Section titled “Only add preload if you mean it permanently”

preload is not just a token. It requests inclusion in a list compiled into browsers, which requires includeSubDomains, a max-age of at least one year, and submission at hstspreload.org.

Removal is the problem. Getting off the list requires a request, and then waiting for browsers to ship a release with the updated list — realistically months, during which every user with an older browser build still enforces it. There is no fast rollback and no way to hurry it.

For a site you control end to end and intend to keep on HTTPS forever, that’s fine. For anything with subdomains you don’t fully control, it is a decision you cannot walk back at the speed you’ll want to.