HSTS Strict-Transport-Security Explained for NZ Sites
What HSTS Strict-Transport-Security does, how to enable it for nginx, Apache and Express, plus includeSubDomains and preload gotchas for NZ sites.
Quick answer
HSTS (HTTP Strict Transport Security) is one response header that tells every browser "for the next year, only ever load this site over HTTPS, even if a user types http:// or follows an insecure link." Once set, your site stops being reachable over plain HTTP for that period. The minimum header is Strict-Transport-Security: max-age=31536000; includeSubDomains. Adding preload lets you submit your domain to the browser-shipped HSTS preload list, so even the very first visit is protected.
If your site does not send HSTS today, the Free Website Security Check flags the missing header as a scanner hsts finding and tells you which snippet to paste.
What HSTS actually does
Every time a browser loads your site, your server has a chance to send back a short instruction in the response: "next time, and every time for the next N seconds, refuse to talk to me over plain HTTP." That instruction is the Strict-Transport-Security header, defined in RFC 6797.
Once a browser has seen the header, it will:
- silently rewrite any
http://yoursite.nz/...URL intohttps://yoursite.nz/...for themax-ageperiod - refuse to connect to your site over plain HTTP for that period, even if the user typed
http:// - refuse to click through a "your connection is not secure" warning during that period
The header is what stops a class of attack where someone briefly forces a visitor over plain HTTP — for example on a coffee-shop Wi-Fi network — to capture session cookies or strip the HTTPS off a redirect (1). HSTS does not fix the redirect itself; it stops the visitor from ever landing on the unsafe version.
A typical NZ school or small-business site should ship this minimum header on every response:
Strict-Transport-Security: max-age=31536000; includeSubDomains
That means: one year (31,536,000 seconds), and apply the rule to every subdomain (e.g. portal.yourschool.nz).
Why HSTS matters for New Zealand sites
HSTS is a one-line change with outsized impact. Three reasons it sits in the NZAI Security baseline:
- The "first visit" problem. Without HSTS, the very first time a visitor reaches your site (typed URL, link from email, search result) is unprotected. A network attacker can briefly downgrade that visit to HTTP and capture whatever they need. HSTS closes the window on the second visit onward — and closes it on the very first visit if your domain is on the preload list.
- CERT NZ names HTTPS-only as a baseline control. "Baseline controls" are the things CERT NZ expects every New Zealand organisation to have done before an incident is investigated (2). A scanner that flags
hstsas missing is pointing at exactly that gap. - Privacy Act 2020 defensibility. Student data is in scope of the Privacy Act 2020 (3). If a misconfiguration leads to a breach, the Office of the Privacy Commissioner looks at what reasonable steps you took. Shipping HSTS is one of the cheapest reasonable steps available.
For the broader educator context (devices, accounts, phishing), see Building Cyber-Safe Habits as an NZ Educator.
The three directives: max-age, includeSubDomains, preload
The HSTS header has three things you can set. Each carries a tradeoff.
max-age
max-age=<seconds> is how long the browser should remember the rule. The IETF and the HSTS preload list submission page both require a minimum of 31536000 seconds (one year) for eligibility (1)(4). Shorter values are valid but give you less protection; longer values make the rule harder to undo if you ever need to roll it back.
A safe starter value is max-age=300 (five minutes) while you test — it gives you a quick exit if something breaks. Move to max-age=31536000 once you are confident.
includeSubDomains
includeSubDomains extends the rule to every subdomain. This is a powerful, irreversible-feeling statement: every *.yourschool.nz hostname is now HTTPS-or-nothing for the next year.
includeSubDomains once every subdomain you own serves HTTPS. If you spin up a plain-HTTP staging.yourschool.nz after enabling it, every visitor's browser will refuse to load the new subdomain and silently rewrite the URL to HTTPS — which then fails because there is no TLS there (1).
For most NZ schools this means: turn it on, then sweep every DNS record and confirm every hostname has a valid cert.
preload
preload opts your domain into the browser-shipped HSTS preload list. Once accepted, the rule is baked into Chrome, Firefox, Safari, Edge and every browser that ships the list — so even a brand-new visitor on a brand-new device gets the protection on their very first visit (4).
Submission is permanent in spirit: removing a domain from the preload list takes months to propagate. Most NZ sites do not need preload to be safe; the basic max-age=31536000; includeSubDomains header is enough for almost every visitor.

The first-visit problem and how preload solves it
HSTS only fires after the browser has seen the header once. On the very first visit — typed URL, link from email, search click — the browser has no prior knowledge and will accept whatever your server offers. If an attacker is positioned on the network at that moment, they can downgrade that first visit.
preload closes the first-visit gap by baking your domain into the browser itself. Every browser that ships the list treats your domain as HSTS-enabled from the very first connection attempt, before any HTTP exchange has happened (4).
The tradeoff: submitting to the preload list is a one-way door. Once your domain is in the list, every subdomain must serve HTTPS, and getting out takes several browser release cycles. For most NZ sites, includeSubDomains without preload is the right balance.
Copy-paste fixes for the four common stacks
These snippets set the minimum recommended header. Paste them, restart the relevant service, and verify with the Free Website Security Check.
nginx
Add inside your server { ... } block:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Reload with nginx -s reload (or sudo systemctl reload nginx on systemd hosts). The always flag ensures the header is set even on error responses (4xx/5xx), which is what you want — it stops downgrade attacks on the error pages themselves.
Apache
Add inside your <VirtualHost>, or in an .htaccess in the document root:
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>
If the header does not appear after reload, the most common cause is a mod_headers mismatch with how the site is hosted — confirm the module is loaded (apache2ctl -M | grep headers).
Express (Node.js)
Use the widely-trusted helmet package:
npm install helmet
Then in your app:
import helmet from 'helmet';
app.use(
helmet({
strictTransportSecurity: {
maxAge: 31536000,
includeSubDomains: true,
preload: false,
},
})
);
Set preload: true only if you have submitted your domain to the preload list and every subdomain serves HTTPS (1).
Cloudflare
If you front your site with Cloudflare, you can enable HSTS from the dashboard:
- Go to SSL → Edge Certificates → HSTS → enable with
max-age=31536000,includeSubDomains, and optionallypreload - Read the warning dialog carefully before submitting to the preload list — it is permanent
- Optionally set the same header at origin so it survives a Cloudflare bypass (e.g. direct API call)
Setting HSTS only at Cloudflare is enough for almost every visitor, but the moment Cloudflare is bypassed (direct origin traffic, an API call, a misconfigured DNS), your site loses the header. Set it at both layers where you can.
Common HSTS mistakes to avoid
From running the free scanner across New Zealand school and small-business sites, the most frequent missteps are:
- Setting HSTS over plain HTTP. HSTS only works over HTTPS. If your site is still reachable over plain HTTP for any reason, the browser will not record the header from an HTTP response (1).
- Adding
includeSubDomainsbefore checking every subdomain. Astagingordevsubdomain on plain HTTP becomes unreachable to most visitors for the next year (1). - Setting
max-agefor a few days "to test". A shortmax-agedoes work for testing, but most production sites want the full year. Anything below 31536000 seconds makes you ineligible for the preload list (4). - Submitting to preload without
includeSubDomains. The preload list requiresincludeSubDomains— submissions without it are rejected (4). - CDN stripping the header. If a CDN or reverse proxy sits in front of your origin, it can strip or rewrite the HSTS header. Verify through the CDN edge, not just from the origin server.
- Forgetting
always(nginx) /Header always(Apache). Withoutalways, the header is only set on 2xx responses, leaving 4xx/5xx pages unprotected (4).
hsts finding reappears after you set the header, the problem is almost always a CDN or reverse proxy stripping it on the way out — not the origin config itself (1).
Verify before you ship
Setting the header is half the job. Two ways to confirm it is live:
1. Run the free NZAI scanner
The Free Website Security Check flags the missing HSTS header as a hsts finding and tells you which snippet to paste. Run it after every config change.
2. curl from the command line
curl -sI https://yoursite.nz | grep -i strict-transport-security
You should see the header name and your configured value. To bypass cache, append a fresh query string (?nocache=1) or test against a URL the cache has not seen.
Knowledge check
Test your understanding of HSTS with these questions. Click or tap each card to flip it and see the answer.
max-age=31536000 and includeSubDomains on Friday. On Monday morning the IT team spins up a new staging.yourschool.nz subdomain on plain HTTP for testing — and it stops responding entirely. What happened, and is it fixable without consequences?tap to flipstaging.yourschool.nz and silently rewrites it to HTTPS. If the subdomain does not serve HTTPS, the user's browser shows an error. Fixing it requires serving HTTPS on the subdomain — there is no way to "undo" HSTS for affected visitors during the max-age period, which is why includeSubDomains should only be added once every subdomain is HTTPS-ready (1).learn.yourschool.nz subdomain for a temporary pilot project that does not have HTTPS ready. What happens?tap to fliplearn.yourschool.nz and silently rewrite to HTTPS, which then fails because there is no TLS there. The preload list also requires includeSubDomains, so the same rule covers every existing subdomain too. The only fix is to set up HTTPS on the new subdomain before launching it — and that is exactly the kind of operational pressure the preload list is designed to apply. Removing a domain from the preload list takes months of browser release cycles (4).curl -sI https://yoursite.nz), not just from the origin server (1).Sources and references
[1] Internet Engineering Task Force. (2012). RFC 6797 — HTTP Strict Transport Security (HSTS). https://datatracker.ietf.org/doc/html/rfc6797
[2] CERT NZ. (2025). Top 11 cyber security tips for your business. https://www.cert.govt.nz/business/guides/top-tips-for-cyber-security/
[3] New Zealand. Parliament. (2020). Privacy Act 2020. https://www.legislation.govt.nz/act/public/2020/0031/latest/whole.html
[4] Chromium Project. (2025). HSTS preload list submission. https://hstspreload.org
[5] Mozilla. (2025). MDN Web Docs — Strict-Transport-Security header. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
What to do next
- Run the Free Website Security Check to confirm your site now sends HSTS (it reports any
hstsfinding as fixed once the header is live). - For the full set of recommended response headers (CSP, X-Frame-Options, Referrer-Policy and friends), see the Security Headers Explained guide.
- For the modern TLS baseline that HSTS builds on, see the TLS 1.2 and 1.3 explained guide.
- For everything else the scanner checks (cookies, exposed files, mixed content, redirects, TLS), the free scanner covers all of it in one pass.
- TLS Certificate Renewal Automation for NZ Sites — Certbot, Let's Encrypt, DNS-01 vs HTTP-01 challenges, and how to keep HTTPS certificates renewed automatically on NZ-hosted sites.
- HTTPS Everywhere: Fixing Mixed Content on NZ Sites — the mixed-content companion guide, including CSP
upgrade-insecure-requests, browser auto-upgrade, andwww↔ apex redirect handling. - Redirect Chains Explained for NZ Sites — why long or insecure redirect chains are bad, and copy-paste nginx/Apache single-301 configs.