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.
The largest of these moves: sixteen references spelled through `let`
aliases across eight modules, plus eight more spelled as a path, plus
five documentation pages.
authelia is also the clearest case for why the two namespaces exist.
`swarm.authelia.url` is needed by *every* hive in the swarm — it says
where to send a browser to authenticate — while running the container is
the business of exactly one host. The client half and the server half
were sharing a namespace whose whole contract is "identical everywhere",
and only one of them could honour it.
`swarm.authelia.oidc.clients` stays where it is for the same reason:
several modules register a client there, gated on authelia running here,
and the registry itself is what the service *is* rather than a decision
about this machine.
One sweep note worth recording: a grep for `swarm.authelia.enable` misses
`swarmCfg.authelia.enable`, because the prefix is whatever the reading
file bound. Grepping the suffix `.authelia.enable` finds both, and found
a reference in swarm.nix that the path-shaped pattern did not.
One commit rather than two because they are not independent: the UI's
`enable` had the controller's as its literal default, so moving the
controller alone would leave the UI's default naming an option that no
longer exists.
The UI keeps that derivation in its new home — it is a view onto the
controller's state and reaches it over that daemon's unix socket, so the
host running the controller is the host that can serve it.
Three spellings had to move together for the UI, not one: the `default`,
the `defaultText` shown in the options doc, and the description prose
that names the old path in words. A grep for the option path finds the
first two.
The sweep also reached outside nix: `swarm-controller`'s crate README and
its `//!` module doc both named the option, as did this repo's own
CLAUDE.md and four pages under docs/. An option's name is API, and its
documentation lives wherever someone thought to write it down.
Three readers, three different questions:
`observability.md` gets the operator's version — what to set (nothing, on an
all-local swarm), what to set elsewhere, what a misconfiguration looks like
(401s and a missing hive), and what turning it off actually costs.
`swarm/secrets.md` extends the existing client-secret row rather than adding
one, because this is a new *reader* of a secret already described. It notes the
one thing that makes this reader unusual: a host unit reads the file in place,
so unlike every other consumer there is no delivery step to get wrong.
`setup.md` gets one bullet under security notes, since a first-run hive gets
the property without doing anything and should know it has it.
Per mara: setup should point at it. The link is placed as a precondition
rather than a see-also -- every step below assumes each credential is
generated where it is read, which is only true all-local.
Per argus: 'with a bound' was missing a word; it now names the actual
120s wait instead of gesturing at one.
The step-3 warning said to keep `--group admins` and left the impression
that a later re-run would fix a missing one. It would not: `user add`
refuses on an existing name, so until `user update` existed the only
repair was hand-editing two files as root. mara asked the question the
warning should have answered — "will the cmd just add the group or do i
get a whole new user?".
Deliberately in this PR rather than #3199's: the sentence only becomes
true once the verb it names exists.
Per mara on the PR: the guide someone follows on a fresh deploy is a
different page from the one they read while debugging, and only the
second existed.
Also fixes a contradiction the request surfaced: setup.md and
swarm/sso.md have told every operator to create '--group admins' since
the bootstrap step existed, while the new rule required 'operators'.
This is the first rule that CONSUMES a group name, so it takes the one
the guide already creates - inventing a second would have meant every
account made by following the guide silently failing the check it was
supposed to pass, and for mara specifically a migration step that now
may not be needed at all.
setup.md's step 3 says why --group is not decoration; the new step 4
says what decides whether the page opens (the group, and the name
resolving) rather than listing a command, because there is nothing to
run. Steps renumbered, including the matrix block's internal 4a-4e.
`setup.md` is the page someone follows on a fresh deploy, and it had no
step for authelia at all — so the operator finished the walkthrough with
a crash-looping container and a 502, having done everything the doc
asked. The warnings added to sso.md and gateway.md only help someone who
is already debugging; this is the page that decides whether they end up
debugging.
New step 3, gated on `swarm.authelia.enable`, placed before matrix
because it is part of getting the front door open. Says plainly that it
is required to finish the install, names the symptom it prevents, and
links sso.md for the detail rather than restating it.
Renumbers matrix (4), spawn (5) and host commands (6), including the
matrix block's own 3a–3e labels, which would otherwise disagree with
their heading.