docs/swarm: the store's init step, its identity, and its first reader
bao operator init stays manual: it emits recovery keys and a root token, so automating it would put the disaster-recovery material on the host it is the recovery path for. The unseal note is split by seal mode, since pkcs11 unseals itself and only shamir needs an operator per boot. secrets.md said nothing reads the store and nothing mints its identity; setup.md said the deployment must supply the certificate. All three are false now. They name the first reader, why that credential and not authelia's OIDC secret, that every failure path leaves the local token in place, and that the minted paths are mkDefaults an operator's own paths beat. Delta sweep clean: 0 hits for useSelfSigned / acme / swarm-services / 'nothing reads' / 'issued and unused'; control returns 12 for serverCertFile. The single 'no reader' hit is a module-eval comment describing the absence arm.
This commit is contained in:
parent
aa784a746d
commit
c1b7be1135
2 changed files with 64 additions and 5 deletions
|
|
@ -55,6 +55,8 @@ neither is a renaming of the other.
|
|||
| authelia subject store | `swarmctl` and `swarm-authelia-bridge` | `users.yml` — one file, read and written by both | `swarmctl`, on the host that runs authelia |
|
||||
| wireguard private key | **the operator** — `wg genkey` | whatever `swarm.wireguard.privateKeyFile` names | always operator-provided; nothing generates this for you |
|
||||
| queue auth-callout nkeys (user seed + account seed) | `swarm-nats-callout-keys` first-boot unit, when `nats.autoGenerateCallout` is set | `/var/lib/swarm-nats-callout/{callout-user,issuer}.seed`, `0600` | operator mints both with `nk` and names them in `nats.calloutUserSeedFile` / `nats.calloutIssuerSeedFile` |
|
||||
| the secret store's own contents | openbao, on first `bao operator init` — **an operator action, not a unit** | `/var/lib/swarm-bao` on the host of whoever runs the store, bind-mounted into the `swarm-bao` container | n/a — there is one store; a hive elsewhere is a *client* of it and holds none of this |
|
||||
| the secret store's unseal material | the HSM/TPM under `deploy.bao.seal = "pkcs11"`; openbao itself under `"shamir"` | in the token; or held by whoever ran `bao operator init`, which is what `"shamir"` means and why it is stated rather than inferred | n/a — only the host running the store seals anything |
|
||||
|
||||
The three keys authelia mints for itself are generated in-container precisely
|
||||
because nothing outside that container ever reads them. **That is the test worth
|
||||
|
|
@ -132,6 +134,29 @@ bounded wait, 120s — and then **fail loudly** rather than skipping. A silent s
|
|||
produces a service whose login button always fails, which is a symptom several
|
||||
layers from its cause.
|
||||
|
||||
The store's **first reader** is the matrix registration token, and it is worth
|
||||
saying why that one: it is an opaque 32-byte value with no second file and no
|
||||
format. Authelia's OIDC secret needs a `.secret` *and* a matching `.digest`, so
|
||||
starting there would have meant debugging "can a reader authenticate and get
|
||||
bytes back" and "did we write authelia's file format right" at once, with an
|
||||
SSO outage as the failure mode.
|
||||
|
||||
`glue-matrix-bao-token.nix` fetches it and writes the file `hive-matrix.nix`
|
||||
already reads, so the homeserver never learns the store exists. Every failure
|
||||
path — no such key, sealed store, unreachable store, empty value — leaves the
|
||||
locally minted token in place, so a hive with no store behaves exactly as it
|
||||
did before.
|
||||
|
||||
⚠️ **Service↔store mTLS is its own trust domain.** A credential you must
|
||||
already hold to authenticate cannot be fetched from the thing it authenticates
|
||||
you to, so the store's identity cannot come from an authority the store
|
||||
distributes — which excludes the hive CA and the swarm CA both, and has nothing
|
||||
to do with the gateway's HTTPS certificates either way. `glue-bao-tls.nix`
|
||||
mints a CA that signs exactly two things, the store's server certificate and a
|
||||
reader's client certificate, and distributes nothing. A deployment with a real
|
||||
internal CA deletes that file and names its own paths in
|
||||
`deploy.bao.serverCertFile` / `clientCaFile`; the store itself has no opinion.
|
||||
|
||||
## The constraint that decides where the root lives
|
||||
|
||||
A hive CA carries `nameConstraints=permitted;DNS:<hive domain>`, and **a swarm
|
||||
|
|
|
|||
Loading…
Reference in a new issue