HSTS in Nginx – Should Strict-Transport-Security Header Be Added in Subdomain Server Blocks?

httphttp-headershttpsnginxssl

Let's take the following nginx.conf configuration file with server blocks for example.com and subdomain.example.com:

http {
    ...

    server {
        listen [::]:80 ipv6only=off default_server;
        server_name example.com;
        return 301 https://example.com$request_uri;
    }
    server {
        listen [::]:443 ipv6only=off ssl default_server;
        server_name example.com;
        add_header Strict-Transport-Security
            "max-age=63072000; includeSubDomains; preload" always;
        ...
    }

    server {
        listen [::]:80 ipv6only=off;
        server_name subdomain.example.com;
        return 301 https://subdomain.example.com$request_uri;
    }
    server {
        listen [::]:443 ipv6only=off ssl;
        server_name subdomain.example.com;
        add_header Strict-Transport-Security
            "max-age=63072000; includeSubDomains; preload" always; # <-- again ???
        ...
    }
}

The includeSubDomains part of the header apparently tells the browser that the header applies to all subdomains as well.

However, if that browser were to visit subdomain.example.com before ever seeing example.com, that wouldn't be of any help, would it? So to cover for this scenario, I need to add the same add_header in all subdomain server blocks too …right?

Best Answer

You are correct that it's better to have the HSTS Strict-Transport-Security header everywhere you need it to make sure a client gets it even if sub.example.com is accessed before example.com or if the cached HSTS information has expired.

The includeSubDomains flag affects all subdomains of where it's present. This means that includeSubDomains on sub.example.com takes effect on *.sub.example.com instead of *.example.com. (This is only natural as it would be bad if e.g. example.co.uk could affect *.co.uk.)

  • If you don't use any sub.sub.example.com you could leave the Strict-Transport-Security header of your subdomains without this flag.

  • subA.example.com can't protect subB.example.com.