diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index a5b3d7c6..2759df60 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -418,6 +418,18 @@ in ''; } ]; + + # The name every reader dials, made resolvable where the store runs. + # Cross-hive traffic always goes via the domain; only what it resolves + # to varies, and a multi-host swarm is the operator's upstream DNS. This + # covers the case that has no upstream record to configure. + # + # ⚠️ DNS only. Bao is deliberately absent from `swarm.serviceDomains` + # and gets no vhost: nginx terminating TLS would strip the client + # certificate, which is how the store authenticates every hive — see + # this file's header. `localNames` is the one half of the sibling + # pattern that applies. + services.hyperhive.gateway.localNames = [ cfg.domain ]; }) (lib.mkIf (hyperhiveCfg.enable && deployCfg.bao.enable && haveServerTls) { diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 73b49a84..ab3de892 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -103,6 +103,8 @@ let # is deployed" from "this host can authenticate to the store". matrixNoBaoIdentity = hive { deploy.matrix.enable = true; }; + baoNames = machine: machine.services.hyperhive.gateway.localNames; + # A priority collision is a property of the *option*, not # of the merged value's interior — nix throws the moment the value is # demanded at all, so `seq`-ing each `serviceConfig` value to WHNF is @@ -250,6 +252,18 @@ let in s ? swarm-bao-matrix-token && s.swarm-bao-matrix-token.requires == [ "swarm-bao-pki.service" ]; } + { + # The name a reader dials has to resolve where the store runs; a + # multi-host swarm resolves it upstream instead. + name = "the store's host answers for the store's name"; + ok = builtins.elem "bao.t.local" (baoNames baoPkcs11); + } + { + # Absence arm, and the one that matters: claiming a name this host does + # not serve points every local reader at the wrong machine. + name = "a hive that does not run the store claims no name for it"; + ok = !(builtins.elem "bao.t.local" (baoNames bare)); + } ]; bad = builtins.filter (c: !c.ok) cases;