Certificate management: from PEM to hot swap
TLS certificates are the most error-prone part of any config — and silent errors are the most dangerous. XServer turns every certificate check into a named diagnostic and supports replacing certificates without downtime.
Overview
12.1 Intro
The traditional experience of certificate problems is "handshake failed, reason unknown": maybe the path is wrong, maybe the format is broken, maybe the key doesn't match the cert, maybe the chain is incomplete. XServer's stance is to turn every failure into a named diagnostic — everything checkable at startup is checked at startup; runtime updates go through atomic replacement. Behind this stands the advantage of an in-house TLS stack: parsing, matching and dispatch are all in our own hands.
12.2 Strict PEM parsing
Private key files parse against three PEM labels under strict pairing rules:
- BEGIN/END tags must pair up by count — "expects exactly one supported PEM block"
- Multiple blocks or a truncated trailing block are never silently ignored: startup fails and names the file
- The three supported private-key labels cover the output shapes of mainstream tooling (the OpenSSL family)
Certificate chains are likewise built completely at assembly (chain construction with backtracking frame stacks); an incomplete chain doesn't wait for the handshake to surface.
12.3 Algorithm-family diagnostics
The most classic case in func_test's TLS diagnostic matrix: take a PKCS#8 RSA private key and rewrite its PEM type declaration to EC — the expected error must name both sides:
certificate uses RSA but private key uses EC
Why both names matter: it tells you "what the certificate is" and "what the key was taken for" at once — usually a swapped file or an edited tag, instantly locatable. Curve-family mismatches (cert P-256 + key P-384) get the same named treatment.
12.4 The SNI table & hot swap
When accepting an intent, the reload coordinator does config-level routing: if the structural comparison is unchanged (endpoints, listeners, topology identical) → certificate hot swap plus script reload; otherwise chapter 13's structural-change rules apply. Which means renewing a certificate is exactly two actions: "overwrite the file + submit a reload".
12.5 Contract
- Checks: PEM pairing, algorithm-family matching and chain building all complete at startup with named diagnostics.
- Dispatch: certificates enter the SNI table per host config and are selected by SNI at handshake, consistent with HTTP-layer routing.
- Renewal: a reload with unchanged structure takes the hot-swap path — atomic table swap under lock; old identities stay reference-protected until in-flight handshakes end.
Common mistakes
- Symptom
- Startup fails; the diagnostic says a file's content isn't the expected type.
- Cause
- tls_cert got the private-key file (or vice versa). Strict PEM parsing exposes this at startup instead of at handshake time.
- Symptom
- Renewing a certificate dropped every connection.
- Cause
- Not knowing the hot-swap path exists — overwrite the file and submit a reload; no process restart needed.
cp new-cert.pem host/tls/
systemctl restart xs /* drops connections */cp new-cert.pem host/tls/
/* submit a reload: certificate hot swap */Exercises
Generate a cert/key with any self-signing tool, enable the TLS port on the demo and verify with curl -k.
Create in turn: a key with a rewritten tag, a cert/key algorithm-family mismatch, a truncated PEM block — record all three diagnostics.
Keep a long-lived connection running (curl --http1.1 -k in a request loop), overwrite the certificate mid-flight and submit a reload; watch whether the connection drops.
Summary
| Point | Conclusion |
|---|---|
| Strict parsing | PEM tags counted in pairs; broken blocks are never silent |
| Named diagnostics | Family mismatches name both sides (cert is X, key is Y) |
| SNI dispatch | Host-level certs → selected at handshake, consistent with HTTP routing |
| Hot swap | Structure-unchanged reload: atomic table swap + reference protection, zero disconnections |
- xrt reference · pem — the PEM block parsing API
- xrt reference · x509 — chain building and algorithm-family detection