kb(whp/admin): document panel HSTS + VM-rebuild lockout recovery
All checks were successful
Build and deploy / deploy (push) Successful in 23s

The WHP panel sends Strict-Transport-Security max-age=31536000
includeSubDomains on every response (correct for prod). When a server
is rebuilt, the regenerated self-signed cert no longer matches what
the admin's browser cached as HSTS-valid, and there is no clickable
'proceed unsafely' escape — the admin is locked out of their own
panel by hostname.

Add a Caution Aside under Network & SSL describing the symptom, the
two-browser HSTS confirmation pattern, and the three recovery paths
(IP-direct + LE issuance, browser HSTS clear, real cert preserved
across rebuilds). Frames LE issuance as a first-day operation, not an
incident response.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-29 09:21:08 -07:00
parent 33d1da92ca
commit 6ee2cf13b0

View File

@@ -77,6 +77,23 @@ Operational controls for HAProxy and system-service certs:
- **HAProxy API Key** — Bearer token used to authenticate against the HAProxy Manager API. After rotating, restart the HAProxy container. - **HAProxy API Key** — Bearer token used to authenticate against the HAProxy Manager API. After rotating, restart the HAProxy container.
- **System Service SSL Certificates** — request a Let's Encrypt cert for system-level services like the WHP panel itself and FTP, by picking the service and the domain name. - **System Service SSL Certificates** — request a Let's Encrypt cert for system-level services like the WHP panel itself and FTP, by picking the service and the domain name.
<Aside type="caution" title="Panel SSL + HSTS — VM rebuild and cert change gotcha">
The WHP panel always sends `Strict-Transport-Security: max-age=31536000; includeSubDomains` on every HTTPS response. That header is part of the panel's defence-in-depth — once a browser has visited the panel over HTTPS, it will refuse to fall back to HTTP and will refuse to accept an untrusted certificate (no clickable "proceed anyway" escape).
**When this bites you:** any time the panel's certificate fingerprint changes for the **same hostname**. Most common cause: rebuilding the VM. A fresh `setup.sh` run regenerates the self-signed `/etc/pki/tls/certs/localhost.crt`. Your browser still has the year-long HSTS rule cached from the previous VM, so it refuses to connect to the new cert. Both Chrome and Firefox enforce HSTS at the browser level.
**Recovery options for the admin who's locked out of their own panel:**
1. **Use the IP directly instead of the hostname.** HSTS is scoped to host names, not IP addresses. Hit `http://<server-ip>:8080/` or `https://<server-ip>:8443/`, log in, then go straight to **Network & SSL → System Service SSL Certificates** and issue a real Let's Encrypt cert for the panel's hostname. Reload the page and the hostname URL works again.
2. **Clear the HSTS rule in your browser.**
- **Chrome / Edge:** `chrome://net-internals/#hsts` → *Delete domain security policies* → enter the panel hostname → *Delete*.
- **Firefox:** start a private window for the panel hostname, OR close Firefox, open `<profile>/SiteSecurityServiceState.txt`, and remove the line beginning with the panel hostname.
3. **Issue a real Let's Encrypt cert before the next rebuild.** Once `whp02.example.com` has a real cert that survives rebuilds (e.g., the LE private key is preserved across rebuilds, or the cert is re-issued as part of post-install automation), the HSTS rule has nothing to argue with.
Issuing a Let's Encrypt cert for the panel hostname is a first-day operation for every new server, and it's how you avoid having to recover from this scenario on rebuild #2.
</Aside>
### Security ### Security
API keys for **external integrations** like WHMCS. Not customer-facing. API keys for **external integrations** like WHMCS. Not customer-facing.