Configuring HSTS in NGINX and NGINX Plus
Setting the Strict Transport Security (STS) response header in NGINX and NGINX Plus is relatively straightforward:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
The always
parameter ensures that the header is set for all responses, including internally generated error responses. Older versions of NGINX (prior to version 1.7.5 or NGINX Plus R5) don’t support the always
parameter and do not set the header on internally generated error responses.
Inheritance Rules for add_header
Directives
NGINX configuration blocks inherit add_header
directives from their enclosing blocks, so you just need to place the add_header
directive in the top‑level server
block. There’s one important exception: if a block includes an add_header
directive itself, it does not inherit headers from enclosing blocks, and you need to redeclare all add_header
directives:
server {
listen 443 ssl;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# This 'location' block inherits the STS header
location / {
root /usr/share/nginx/html;
}
# Because this 'location' block contains another 'add_header' directive,
# we must redeclare the STS header
location /servlet {
add_header X-Served-By "My Servlet Handler";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
proxy_pass http://localhost:8080;
}
}
Testing HTTP Strict Transport Security with Care
Once a client is presented with the HSTS policy, it caches the information for the specified max-age
period. During that period, the browser refuses to access the web service over unencrypted HTTP, and refuses to grant exceptions to certificate errors (if the site previously presented a valid, trusted certificate). If you specify the includeSubDomains
parameter for an HSTS policy, these restrictions also apply to all subdomains of the current domain.
It’s very difficult to back out an HSTS policy in order to remove the HTTPS version of a website or service. When you test HSTS, use a very short max-age
timeout and ensure you’re comfortable with the effects and the obligation to maintain an HTTPS version of your site. When you first go live with your HSTS policy, keep max-age
small and increase it only when you’re confident about doing so.
Does Every HTTPS Response Need to Have an STS Header?
The goal is to present the HSTS policy to your users as soon as possible when they begin the HTTPS session. If they don’t receive the HSTS policy during the session, they remain vulnerable to future HTTP hijacking attacks.
The browser needs to observe the STS header only once, so it’s not strictly necessary to add it to every location
block and every response. However, adding it to just the home page or login page is probably not sufficient, and if you add the header only to cacheable responses, a client might not see it. Make sure you cover as much of your URL space as reasonably possible, with special attention to dynamic (non‑cacheable) content.