HTTP Strict Transport Security (HSTS) and HTTP/2 are both fundamental security and performance technologies for modern web applications, and enabling them together is a common goal. HSTS forces browsers to only connect to your site over HTTPS, while HTTP/2 offers significant performance improvements over HTTP/1.1, especially for secure connections. The key to enabling them effectively is to ensure your web server is configured to serve HTTPS traffic using HTTP/2 and that HSTS is correctly implemented.
Here’s how to set it up, focusing on Nginx as a common web server.
Enabling HTTP/2 for HTTPS on Nginx
First, ensure your Nginx version supports HTTP/2. Most modern versions do. The critical directive is listen with the http2 parameter.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL configuration
ssl_certificate /etc/nginx/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
# Other SSL settings for security
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off; # Consider disabling for better forward secrecy
# ... rest of your server configuration (root, index, location blocks)
}
What this does:
The listen 443 ssl http2; directive tells Nginx to listen on port 443 (the standard HTTPS port), enable SSL/TLS encryption, and use the HTTP/2 protocol for incoming connections. The [::]:443 part ensures it’s listening on IPv6 as well. The ssl_certificate and ssl_certificate_key directives point to your SSL certificate and private key, which are essential for HTTPS. The other ssl_ directives are for hardening your TLS configuration, which is crucial for overall security.
Implementing HSTS
HSTS is implemented via an HTTP response header. You’ll add this to your HTTPS server block.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL configuration (as above)
ssl_certificate /etc/nginx/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS Header
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# ... rest of your server configuration
}
# Important: You might also have an HTTP server block that redirects to HTTPS.
# Ensure this block DOES NOT have the HSTS header.
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
What this does:
The add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; directive adds the HSTS header to all responses served from this HTTPS block.
max-age=31536000: This is the duration (in seconds) for which the browser should remember to only connect via HTTPS.31536000seconds is one year.includeSubDomains: This directive tells the browser to apply the HSTS policy to all subdomains ofyourdomain.comas well. This is highly recommended for comprehensive security.preload: This is an opt-in directive. If you includepreload, you can submit your domain to HSTS preload lists (maintained by browsers like Chrome). Once a domain is on a preload list, browsers will never allow an HTTP connection to it, even on the first visit, before even receiving your HSTS header. Be absolutely sure your HTTPS setup is solid before addingpreloadand submitting.
The always parameter ensures the header is added regardless of the response code. The separate HTTP block (listening on port 80) is crucial for redirecting all incoming HTTP traffic to HTTPS. It must not have the HSTS header, as HSTS is only valid over HTTPS connections.
Verifying Your Setup
-
Check HTTP/2:
- Use your browser’s developer tools (e.g., Chrome’s Network tab). After loading your site over HTTPS, inspect the "Protocol" column for requests. You should see
HTTP/2. - Alternatively, use
curl:
Look forcurl -I --http2 https://yourdomain.comHTTP/2 200in the output.
- Use your browser’s developer tools (e.g., Chrome’s Network tab). After loading your site over HTTPS, inspect the "Protocol" column for requests. You should see
-
Check HSTS:
- Use your browser’s developer tools. Go to the Security tab or inspect the response headers for any resource served from your domain over HTTPS. You should see the
Strict-Transport-Securityheader with the values you configured. - You can also use online tools like
hstspreload.org(though this specifically checks for preload eligibility, not just basic HSTS).
- Use your browser’s developer tools. Go to the Security tab or inspect the response headers for any resource served from your domain over HTTPS. You should see the
The preload Directive Gotcha
The preload directive is powerful but irreversible for a given browser installation. If you add preload and then later decide to remove HSTS or have an issue with your HTTPS configuration, users whose browsers have already processed the preload directive will be unable to access your site via HTTP or HTTPS until the preload list is updated (which can take months) or they manually clear their browser’s HSTS cache.
Therefore, a safe rollout strategy is:
- Implement HSTS with
max-ageandincludeSubDomainsbut withoutpreload. - Monitor your site and logs for any issues.
- Once confident, add
preload. - Submit your domain to
hstspreload.org.
This ensures that browsers that have already cached the preload directive will continue to enforce it, while new visitors or those who haven’t yet encountered the preload directive will still benefit from the max-age setting.
By combining HTTP/2 for performance and HSTS for security, you create a robust and modern web experience for your users. The next step is often understanding how to manage certificate renewals seamlessly to avoid HSTS-related downtime.