Chapter 12 / 51
Volume 2 · Configuration & Assembly

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

Positioning: certificates come down to three things — the format is right (12.2), the pair matches (12.3), and you can renew (12.4). Every error sample here comes from func_test's TLS diagnostic matrix and is reproducible.

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:

Error shape (verbatim test assertion)
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

at assembly: hosts[] (domain set, cert, key) → build the SNI table │ reload (endpoints/structure unchanged, cert files changed) ▼ certificate hot swap TlsTableRefresh: atomic table swap under lock old identities protected by reference counts → released only after in-flight handshakes finish │ ▼ every new handshake uses the new certificate (no window, no restart)

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

fullchain and key swapped
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.
Restarting after replacing a certificate
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.
✗ Unnecessary
cp new-cert.pem host/tls/
systemctl restart xs   /* drops connections */
✓ Right
cp new-cert.pem host/tls/
/* submit a reload: certificate hot swap */

Exercises

BasicStand up an HTTPS site

Generate a cert/key with any self-signing tool, enable the TLS port on the demo and verify with curl -k.

Acceptance: the TLS endpoint handshakes and returns /json.
AdvancedReproduce the diagnostic matrix

Create in turn: a key with a rewritten tag, a cert/key algorithm-family mismatch, a truncated PEM block — record all three diagnostics.

Acceptance: each message names "which file, what's wrong".
ChallengeZero-downtime certificate swap

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.

Acceptance: zero failed requests in the loop; new handshakes use the new certificate (compare two openssl s_client runs).

Summary

PointConclusion
Strict parsingPEM tags counted in pairs; broken blocks are never silent
Named diagnosticsFamily mismatches name both sides (cert is X, key is Y)
SNI dispatchHost-level certs → selected at handshake, consistent with HTTP routing
Hot swapStructure-unchanged reload: atomic table swap + reference protection, zero disconnections
xrt further reading