~/blog / hsts-explained

What is HSTS and should you enable it?

// published 2026-04-17

HSTS — HTTP Strict Transport Security — is a single response header that tells browsers "from now on, only talk to my domain over HTTPS, and don't let the user click through certificate warnings." It's one of the highest-leverage security headers you can deploy, and it's one of the easiest to misconfigure in ways that bite hard.

What HSTS protects against

Two attacks:

  1. SSL stripping. User types yourdomain.com (no protocol). Browser defaults to HTTP. Attacker on the same network intercepts the initial HTTP request and serves a downgraded, unencrypted version of your site. HSTS prevents this by forcing the initial request to HTTPS even when the user typed no protocol.
  2. User-ignored certificate warnings. If your cert is misissued/expired, a normal browser shows a warning the user can usually bypass. With HSTS, the browser refuses to proceed — no "Advanced → Accept risk" button.

Check whether you have HSTS configured with the Security Headers Checker.

The header format

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Deploy it safely

HSTS is self-inflicted damage if you turn it on wrong. The staged rollout:

Stage 1 — test with short max-age

Strict-Transport-Security: max-age=300

5 minutes. Enough to verify the header is being served from every origin you run; short enough to recover if you discover a subdomain that doesn't have HTTPS yet.

Stage 2 — bump to a real value

Strict-Transport-Security: max-age=31536000

1 year. If anything is going to break, it'll surface within the first day. Leave it running for a week before going further.

Stage 3 — add includeSubDomains

Only do this after you've audited every subdomain. That internal admin dashboard at admin.yourdomain.com? If it's HTTP-only, adding includeSubDomains will lock your staff out. Same for every legacy redirector, marketing microsite, or third-party service hosted on a subdomain.

Stage 4 — preload

Submit to hstspreload.org. Once accepted, your domain gets compiled into the HSTS preload list in every major browser. This is a one-way door — removing from the preload list takes months. Only do this after you've run with includeSubDomains and 1-year max-age in production for at least a few weeks.

When HSTS bites back

One-line deployment examples

nginx:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Apache:

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Rails (config/application.rb):

config.ssl_options = { hsts: { expires: 1.year, subdomains: true } }

After deploying, re-run the Security Headers Checker to confirm the header is being served and graded as "strong".


check_your_own_domain
Run the free Security Headers Checker to diagnose this on any domain.
[ Open Security Headers Checker ]
// related_reading