Skip to main content

HSTS on HostBible: enable HTTP Strict Transport Security safely (and avoid getting locked out)

Force HTTPS safely with HSTS on HostBible—use a staged rollout, verify headers and redirects, test subdomains, and follow a lockout recovery plan if something goes wrong.

Z
Written by Zoe Handscomb
Updated over 3 months ago

HSTS (HTTP Strict Transport Security) is a browser-enforced rule that tells visitors’ browsers: “Only use HTTPS for this domain for the next N seconds.” Once a browser receives your HSTS header over HTTPS, it will automatically upgrade future HTTP requests to HTTPS and won’t allow click-through on invalid certificate warnings—which is great for security, but it’s exactly why misconfigurations can lock you out. (OWASP Cheat Sheet Series)

Prerequisites

Before enabling HSTS, your site must already load correctly over HTTPS with a valid certificate, and HTTP → HTTPS redirects should already be working. (HostBible hosting plans include HTTPS/SSL; make sure it’s active for your domain first.) (hostbible.com)


What HSTS does (and why it can lock you out)

When a browser receives:

Strict-Transport-Security: max-age=...

…it caches the policy for max-age seconds and will refuse to use HTTP for that hostname during that time. If HTTPS breaks (expired cert, hostname mismatch, removed SSL, wrong redirect), affected users can’t “bypass” the warning while HSTS is active. (OWASP Cheat Sheet Series)

Key directives you’ll choose from:

  • max-age=SECONDS — how long browsers remember the rule. (MDN Web Docs)

  • includeSubDomains — applies HSTS to all subdomains too (powerful, higher risk). (MDN Web Docs)

  • preload — requests inclusion in browser preload lists (treat as a long-term commitment). (MDN Web Docs)


Test-first rollout (recommended)

This guide is intentionally test-focused. You’ll test before enabling HSTS, enable with a tiny max‑age, then test again, then increase max‑age in stages.

Step 1 — Test your current HTTPS + redirects (before HSTS)

Replace example.com with your real domain.

1A) Confirm HTTPS works (no errors)

macOS / Linux

curl -I https://example.com curl -I https://www.example.com

Windows (PowerShell)

curl.exe -I https://example.com curl.exe -I https://www.example.com

Good result looks like:

  • Status is 200, 301, or 302 (depending on your setup)

  • No TLS/certificate errors

Bad result looks like:

  • curl: (60) SSL certificate problem: ...

  • curl: (51) SSL: no alternative certificate subject name matches ...

  • Timeouts / connection failures

If you see “bad” results here, stop and fix HTTPS before proceeding.

1B) Confirm HTTP → HTTPS redirects behave correctly

curl -I http://example.com curl -IL http://example.com

Good result looks like:

  • First response is a redirect (301 or 308) to https://...

  • Final response (with -L) is the working HTTPS page

Bad result looks like:

  • http:// returns 200 OK (no redirect)

  • Redirect loops (repeating Location: back and forth)

  • Redirects to the wrong hostname (e.g., to a subdomain that doesn’t have SSL)


Step 2 — Enable HSTS on HostBible (start tiny)

On HostBible’s cPanel-based hosting, the safest “quick rollback” method is to add the header at the site level (so you can change it fast if needed). HostBible support commonly covers cPanel-related hosting tasks. (hostbible.com)

Option A (recommended for most sites): add HSTS in your site’s .htaccess

  1. Log in to your HostBible Client Area and open cPanel. (hostbible.com)

  2. Open File Manager

  3. Go to your site’s document root (often public_html/ or the folder for your domain)

  4. Edit (or create) the .htaccess file

  5. Add this block near the top:

<IfModule mod_headers.c>   # HSTS: start with 5 minutes to reduce lockout risk during testing   Header always set Strict-Transport-Security "max-age=300" env=HTTPS </IfModule>

Why this is “safer”: if anything goes wrong, the worst-case browser lock is ~5 minutes for users who already received the header.

If you get a 500 error after saving, remove the new lines and try without always:

Header set Strict-Transport-Security "max-age=300" env=HTTPS

Then re-test.

Option B (VPS/Dedicated): set HSTS at the web server config level

If you manage your own server configuration, you can set the header at the vhost/server block level instead. (The testing and rollout plan below stays the same.)


Step 3 — Verify the HSTS header is present (immediately after enabling)

3A) Check that HTTPS responses include the header

curl -sI https://example.com | grep -i strict-transport-security

Good result looks like:

Strict-Transport-Security: max-age=300

Bad result looks like:

  • No output at all (header missing)

  • Multiple lines (duplicate headers)

To check duplicates:

curl -sI https://example.com | grep -i strict-transport-security | wc -l

Good: 1
Bad: 2 or more → remove duplicates (pick one place to set it: server OR app OR .htaccess).

3B) Confirm the header appears on the final HTTPS response after redirects

curl -IL http://example.com | grep -i strict-transport-security

Good: you see the header at least once on the HTTPS response in the chain.

Note: Browsers only honor HSTS delivered over HTTPS; you can’t “turn it on” or “turn it off” via plain HTTP. (MDN Web Docs)


Safe rollout plan (max‑age stages)

Once max-age=300 is verified, increase in stages. A practical schedule:

Stage 1 — 5 minutes (already done)

Strict-Transport-Security: max-age=300

Stage 2 — 1 day

Strict-Transport-Security: max-age=86400

Stage 3 — 1 week

Strict-Transport-Security: max-age=604800

Stage 4 — 1 month

Strict-Transport-Security: max-age=2592000

Stage 5 — 6–12 months (common long-term setting)

Strict-Transport-Security: max-age=31536000

Rule: don’t move to the next stage until you can run all tests again and everything looks “good”.


includeSubDomains: only enable if every subdomain is HTTPS-ready

includeSubDomains is a security win, but it increases lockout risk because one broken subdomain becomes a problem for users once their browser has cached the policy. (OWASP Cheat Sheet Series)

includeSubDomains readiness checklist

Before adding it, confirm:

  • Every subdomain you use has a valid certificate and works over HTTPS

  • Every subdomain redirects HTTP → HTTPS (or at least serves HTTPS cleanly)

  • You’ve considered “hidden” or internal subdomains that still exist in DNS

If you’re aiming for preload later, note that preload applies to all subdomains, including internal ones. (hstspreload.org)

Test your subdomains (copy/paste pattern)

Create a list of subdomains you actually use (examples: www, blog, shop, app, api, etc.) and test each:

for host in www.example.com blog.example.com api.example.com; do   echo "== $host =="   curl -I "https://$host" | head -n 5 done

Bad result examples:

  • certificate errors (curl exits with (60) or (51))

  • timeouts

  • redirects to HTTP

Enable includeSubDomains (only after it’s clean)

Start with a moderate max-age first:

Header always set Strict-Transport-Security "max-age=604800; includeSubDomains" env=HTTPS

Then re-run:

  • curl -I https://example.com | grep -i strict-transport-security

  • subdomain tests (above)


preload: treat as “hard to undo”

preload is used to request inclusion in browser HSTS preload lists. It’s powerful because it protects even first-time visitors—but it’s also the hardest to roll back. (Chrome for Developers)

Preload requirements (must meet all)

To be eligible, your site must serve an HSTS header on the base domain where:

  • max-age is at least 31536000 (1 year)

  • includeSubDomains is present

  • preload is present (hstspreload.org)

Also, if www exists in DNS, it must support HTTPS as well. (hstspreload.org)

Preload header value

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

Recommendation: don’t add preload until you’ve run with includeSubDomains safely for a while and you’re confident all current and future subdomains will remain HTTPS-only.


Lockout prevention and recovery plan (bookmark this)

This is the part that saves the most time if something goes wrong.

Lockout prevention checklist

Do these before increasing max‑age beyond a short test window:

  1. Start with max-age=300, verify, then increase gradually (don’t jump to 1 year on day one).

  2. Inventory subdomains (current + likely future). If you can’t guarantee them, delay includeSubDomains.

  3. Make sure you can still access your hosting controls without relying on the website (HostBible Client Area, cPanel access, File Manager, etc.). (hostbible.com)

  4. Keep a “break glass” path:

    • Know exactly where your .htaccess is

    • Keep a copy of the last working version

    • Make sure another team member has access too

Recovery: “I enabled HSTS and now I’m locked out”

First, understand what’s happening:

  • HSTS means the browser refuses HTTP and may refuse to bypass certificate warnings. (OWASP Cheat Sheet Series)

  • So the fix is almost always: restore working HTTPS, then adjust HSTS safely.

Scenario A — HTTPS certificate is broken / expired / wrong hostname

Fix: restore valid HTTPS for the affected hostname(s).

  • Use HostBible control access (Client Area/cPanel/File Manager) to fix config and renew/restore SSL. (hostbible.com)

  • Once HTTPS works again, decide whether to keep HSTS or reduce it.

Scenario B — You need to disable HSTS (rollback)

To disable, you must send a new header over HTTPS with max-age=0 (you cannot disable HSTS over HTTP). (MDN Web Docs)

Set:

<IfModule mod_headers.c>   Header always set Strict-Transport-Security "max-age=0" env=HTTPS </IfModule>

Then verify:

curl -sI https://example.com | grep -i strict-transport-security

Important: If you simply remove the header, browsers that already cached it will continue enforcing it until the original expiry time. Setting max-age=0 is the explicit “turn off” signal. (MDN Web Docs)

Scenario C — You enabled includeSubDomains but one subdomain isn’t ready

Fix order:

  1. Restore HTTPS on that subdomain (preferred).

  2. If you must unwind quickly, temporarily set max-age=0 on the base domain (and on any subdomain that also sends its own HSTS header). Then rebuild with a safer staged plan.

Scenario D — You used preload and now want to undo it

Expect this to take longer than normal rollback. Preload is intended as a long-term commitment and can have “hard to undo” consequences. (OWASP Cheat Sheet Series)
If you’re not 100% sure, don’t enable preload yet.


Quick “good vs bad” reference (copy/paste)

✅ Good (safe test stage)

Strict-Transport-Security: max-age=300

✅ Good (long-term, no subdomains)

Strict-Transport-Security: max-age=31536000

✅ Good (all subdomains HTTPS-ready)

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

⚠️ Risky (only do if you truly want preload)

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

❌ Bad (header missing on HTTPS)

No Strict-Transport-Security header on https://... responses.

❌ Bad (subdomain not HTTPS-ready + includeSubDomains enabled)

Any subdomain fails TLS or redirects incorrectly.

Did this answer your question?