feat(nix): make the swarm CA hierarchy opt-in

A swarm's services and its hives can live on different hosts, and a host
has no way to tell whether it is the one holding the root — so setting
the swarm CA up is an operator action, not something a host infers.
`swarm.ca.autoConfigure` is off by default and is the only thing that
issues a hive sub-CA, which is also the only case that *can*: signing
one needs the root's private key, and that key is deliberately not on a
hive host otherwise.

With the flag off, a hive self-signs its CA exactly as it always has.
That keeps a plain hive working out of the box; what it gives up is
membership of a swarm's trust hierarchy, which is the right thing to
give up for a hive nobody has federated.

Replaces a default derived from `swarm.peers == { }`. That read "no
peers declared" as "everything is local", which is not the same claim —
a hive can belong to a swarm it has not declared yet, or to one whose
services run elsewhere entirely.
This commit is contained in:
atlas 2026-08-05 15:11:22 +02:00 committed by mara
commit cc74a2c1f6
3 changed files with 118 additions and 78 deletions

View file

@ -52,23 +52,25 @@ in
options.services.hyperhive.swarm.ca = {
autoConfigure = lib.mkOption {
type = lib.types.bool;
default = hyperhiveCfg.swarm.peers == { };
defaultText = lib.literalExpression "services.hyperhive.swarm.peers == { }";
example = false;
default = false;
example = true;
description = ''
Generate the swarm root CA on this host when it is missing.
Run the whole swarm CA on this one host: generate the swarm
root when it is missing, and issue this hive's CA under it.
Defaults to true exactly while this hive declares no peers
an all-on-one-host swarm has no cross-hive trust to establish,
so it should cost no configuration. Declaring a peer turns it
off, because a hive that has peers is by definition not the
only place a root could come from, and a second independently
generated root is not a swarm root at all. Set it explicitly
to `true` on the host that does hold the root, or to `false`
to require the operator to provide it.
**Off by default, deliberately.** A swarm's services and its
hives can live on different hosts, and this host has no way to
tell whether it is the one holding the root so the swarm CA
is something an operator sets up, not something a host decides
it is. Turn this on for an all-on-one-host deployment (dev
boxes, single-hive swarms) and get the hierarchy for free.
Turning this off does not disable anything else: the root is
read from the same `stateDir` either way.
With it off, both artifacts are operator-provided: the root
under `stateDir`, and this hive's CA under
`services.hyperhive.tls.stateDir`. A hive given neither keeps
the self-signed CA it has always had it simply isn't part of
a swarm's trust hierarchy, which is the correct outcome for a
hive nobody has federated yet.
'';
};