Expand description
The certificate as swappable state, not a listener to rebind.
This server holds long-lived connections — com.atproto.sync .subscribeRepos is a firehose relays and indexers keep open for hours —
so a renewal cannot mean tearing down the listener or the server to pick
up a new certificate. rustls already has the seam for this:
[rustls::server::ResolvesServerCert] is consulted once per handshake,
not once per connection’s lifetime, so a resolver that hands back a
different [CertifiedKey] after a swap changes what new handshakes see
without touching a byte of an established connection — the certificate
only ever participates in the handshake that created the connection.
One SwappableCert is built once, wrapped in the one
rustls::ServerConfig this process builds, and lives for the process’s
whole life. Renewal calls SwappableCert::swap; nothing else about the
listener or the server changes.
§Why one ArcSwap<CertifiedKey>, not two fields
A certificate and its private key are useless separately and dangerous if
ever mismatched — a reader that saw a new cert paired with an old key (or
vice versa) mid-update would hand out a ServerHello that fails on the
client end at best and misissues at worst. [CertifiedKey] already
bundles the chain, the signing key and the OCSP response as one value, so
swapping that value under [arc_swap::ArcSwap] is one atomic pointer
store: every reader sees either the whole old bundle or the whole new one,
never a mix.
Structs§
- Swappable
Cert - A certificate and key that can be swapped out from under live handshakes.