From 0c50913db929b14afbca94980824772af24b8a78 Mon Sep 17 00:00:00 2001 From: atlas Date: Wed, 16 Sep 2026 23:29:39 +0200 Subject: [PATCH] docs/swarm/credentials.md: mTLS cert is per-identity, not per-host Two lines still framed the invariant as one file total: line 19 ('plus exactly one file') and line 21 ('the only credential on disk') implied a single mTLS cert page-wide, contradicting the earlier fix that made line 26 say 'every host has at least one'. Agents and swarm-level services each need their own identity certificate, so a host running several holds several. Restate both as per-identity, keep the target shape (store + certs on disk, nothing else) unchanged. Also relax the touching-a-credential rule: moving a secret into bao without resolving its renewal strategy in the same change is acceptable while the migration to this shape is in progress, provided a follow-up issue is opened to settle renewal. Refs #4445 --- docs/swarm/credentials.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/swarm/credentials.md b/docs/swarm/credentials.md index 639a16b5..680848b6 100644 --- a/docs/swarm/credentials.md +++ b/docs/swarm/credentials.md @@ -16,14 +16,16 @@ store — bao — lives in the memory of the process that asked for it and nowhere else: not in a state directory, not in a bind-mounted file, not in a systemd credential, not in a rendered config, not for a moment before a unit deletes it. The target isn't a shorter list of secret files. It's the store, -plus exactly one file. +plus one file per identity. -**That one file is the mTLS client certificate, and it's the only credential -on disk.** It has to be a file, and the reason is the whole asymmetry: the -certificate is what authenticates a principal to the store, so it's the one -credential that can't be fetched from the store. Something has to exist on -disk before the first request, or there's nothing to make the request with. -Every host has at least one; its only power is to ask the store for the rest. +**Those files are mTLS client certificates, one per identity, and they're +the only credential on disk.** Each has to be a file, and the reason is the +whole asymmetry: the certificate is what authenticates a principal to the +store, so it's the one credential that can't be fetched from the store. +Something has to exist on disk before the first request, or there's nothing +to make the request with. Every identity — an agent, a swarm-level service — +needs one; a host running several holds several, and its only power is to +ask the store for the rest. `swarm-bao.nix:529-533` states the rule for the nix option that carries it: this is _"the credential an operator places by hand"_, and _"a path, never a value."_ A literal in a nix expression lands in the nix store — @@ -68,3 +70,8 @@ A pull request that touches a credential can't: - give a host or container an out-of-band credential that isn't the store mTLS leaf — one out-of-band credential per principal is the whole point of the store + +While the swarm's credential path is still moving to this shape, a PR that +moves a secret into bao is allowed to leave its renewal strategy unresolved, +provided it opens a follow-up issue to settle renewal. That's a migration-era +allowance, not a standing exception to the renewal-strategy rule above.