diff --git a/docs/swarm/ca.md b/docs/swarm/ca.md index 45b2c39c..19cd15eb 100644 --- a/docs/swarm/ca.md +++ b/docs/swarm/ca.md @@ -24,7 +24,7 @@ the root, so setting the swarm CA up is an operator action rather than something a host assumes. Turn it on for an all-on-one-host deployment and the hierarchy costs no configuration. -It defaults from `services.hyperhive.enableAllLocalDefaults`, the single +It defaults from `services.hyperhive.deploy.singleHostSwarm`, the single switch that says "this box is the whole deployment". **A hive given neither artifact keeps the self-signed CA it has always diff --git a/docs/swarm/secrets.md b/docs/swarm/secrets.md index d43012f9..5f25a132 100644 --- a/docs/swarm/secrets.md +++ b/docs/swarm/secrets.md @@ -86,7 +86,7 @@ scraped; otherwise no secret is needed and none is placed. ### Minting the queue's callout nkeys `nats.autoGenerateCallout` mints both keypairs on the host before the queue -starts. It is on by default only under `enableAllLocalDefaults` — the one +starts. It is on by default only under `singleHostSwarm` — the one topology where the queue, its responder and the operator are the same person. On every other topology, mint them yourself: diff --git a/docs/swarm/services.md b/docs/swarm/services.md index 48b02b7f..24efda7b 100644 --- a/docs/swarm/services.md +++ b/docs/swarm/services.md @@ -1,20 +1,24 @@ # Swarm-wide services -Some things exist once per **swarm**, not once per hive: the forge, the -matrix homeserver, the SSO provider, the CA. Two options say where the -optional ones live, and everything else derives: +Some things exist once per **swarm** rather than once per hive. Two +options say where the optional ones live, and everything else derives: ```nix -services.hyperhive.enableAllLocalDefaults = true; # everything on this box +services.hyperhive.deploy.singleHostSwarm = true; # everything on this box # or, for a dedicated services host with hives elsewhere: -services.hyperhive.swarm.enableRequiredServices = true; +services.hyperhive.deploy.allSwarmServices = true; ``` -`enableAllLocalDefaults` is the all-on-one-box switch: it defaults both -`swarm.enableRequiredServices` (the shared services run here) and -`swarm.ca.autoConfigure` (the swarm CA is generated here). Each derived -toggle can still be set on its own, so "all local except X" needs no -further option. +**`deploy.allSwarmServices` is what "the swarm's shared services run +here" means: every once-per-swarm service that is *optional* takes its +`enable` from it.** That is the whole rule, stated once — the per-service +sections below do not repeat it, so a service that stops deriving is a +visible difference rather than one more paragraph saying the same thing. + +`singleHostSwarm` is the all-on-one-box switch above it: it defaults +both `deploy.allSwarmServices` and `swarm.ca.autoConfigure` (the swarm CA +is generated here). Each derived toggle can still be set on its own, +which wins, so "all local except X" needs no further option. **Both default to off**, and that is deliberate: a host cannot tell whether it is meant to be the swarm's service host, so this is an @@ -33,10 +37,10 @@ Those two options are what makes the difference between deployments, so the shapes worth naming are the ones they produce: - **All-local.** Everything on one machine: - `enableAllLocalDefaults = true`. Setup is automatic apart from + `singleHostSwarm = true`. Setup is automatic apart from choosing a domain and creating the first user. - **Services on the swarm controller host.** - `swarm.enableRequiredServices = true` there; the required services + `deploy.allSwarmServices = true` there; the required services deploy together on that host, with hives elsewhere. - **Fully spread out.** One container / VM / machine per service, somewhere. @@ -64,8 +68,7 @@ One authelia per swarm, in a `swarm-authelia` container, at provider, differentiated by roles and claims rather than by mechanism — there is one IdP and one auth path. -- **`deploy.authelia`** — run the container here. Defaults from - `swarm.enableRequiredServices`. +- **`deploy.authelia`** — run the container here. - **`swarm.authelia.url`** — where clients are sent to authenticate. Present on **every** hive, defaulting to this host's own instance only when this module is the thing running it; otherwise `null`, and a hive @@ -98,10 +101,8 @@ one Grafana, in two containers at `metrics.` and `grafana.`. Two containers rather than one so Grafana can be restarted or broken without taking the time-series database with it. -Both follow `swarm.enableRequiredServices` like authelia and matrix, so -the swarm's service host gets them with everything else. They derive -together: a store with no UI is unreadable and a UI with no store is -empty. To run one without the other, set it directly: +They derive together: a store with no UI is unreadable and a UI with no +store is empty. To run one without the other, set it directly: ```nix services.hyperhive.deploy.victoriametrics.enable = true; @@ -132,9 +133,8 @@ the collector is the only intended writer. ### Logs (VictoriaLogs) The swarm's service containers ship their journals to one VictoriaLogs at -`logs.`, behind the same SSO as everything else. It follows -`swarm.enableRequiredServices` too, and the collector below is what writes -to it. +`logs.`, behind the same SSO as everything else. The +collector below is what writes to it. **Reading them.** Open Grafana, pick **Explore**, and choose the `VictoriaLogs` datasource — it is provisioned for you. Grafana's *Logs @@ -160,9 +160,8 @@ and exports to `otel.endpoint`, doing both when both are configured. It also holds the upstream credential, which is why no hive and no agent needs one. -It follows `swarm.enableRequiredServices` like the services above, in a -`swarm-otel` container. Its `swarm.otel.port` defaults to `4319` rather -than OTLP's usual `4318`, which the hive tier already uses — swarm +It runs in a `swarm-otel` container. Its `swarm.otel.port` defaults to +`4319` rather than OTLP's usual `4318`, which the hive tier uses — swarm containers share the host's network namespace, so two collectors on one port is a coin toss at runtime rather than an error at build time. diff --git a/docs/swarm/ui.md b/docs/swarm/ui.md index 10bd72ee..67d5e3e4 100644 --- a/docs/swarm/ui.md +++ b/docs/swarm/ui.md @@ -12,7 +12,7 @@ answers for one host. This one is the view *across* hives. services.hyperhive.deploy.swarm-ui.enable = true; # defaults to deploy.swarm-controller.enable ``` -Derived from the controller rather than from `enableRequiredServices`: +Derived from the controller rather than from `allSwarmServices`: the UI is a view onto the controller's state and reaches it over that daemon's socket, so the host that runs the controller is the host that can serve the UI. A hive that merely *uses* a swarm has nothing to serve. diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index ebc9f7fd..16b4ce8f 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -110,6 +110,25 @@ in [ "services" "hyperhive" "swarm" "victorialogs" "retentionPeriod" ] [ "services" "hyperhive" "deploy" "victorialogs" "retentionPeriod" ] ) + + # The switch over all of the above, and the name changes with the path + # because the old one described the wrong subject: those services are + # required of the SWARM, while the option says whether THIS host runs + # them. `allSwarmServices` is mara's own phrasing of what it means. + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "enableRequiredServices" ] + [ "services" "hyperhive" "deploy" "allSwarmServices" ] + ) + + # The mode above that one. It sat at the TOP of `services.hyperhive`, + # which is the same defect one tier up: that namespace is everything + # about hyperhive, not the settings of a single hive. The new name says + # what the mode asserts — the whole swarm runs on this host — instead of + # naming its mechanism. + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "enableAllLocalDefaults" ] + [ "services" "hyperhive" "deploy" "singleHostSwarm" ] + ) ]; # ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the @@ -139,9 +158,8 @@ in description = '' Run the swarm's metrics store on this host. - Derives from - {option}`services.hyperhive.swarm.enableRequiredServices` together - with {option}`services.hyperhive.deploy.grafana.enable`: a store + Paired with + {option}`services.hyperhive.deploy.grafana.enable`: a store with no UI is unreadable and a UI with no store is empty, so there is no sensible deployment that takes one and not the other from that switch. Set either directly to run exactly one. @@ -154,10 +172,8 @@ in description = '' Run the swarm's log store on this host. - Derives from - {option}`services.hyperhive.swarm.enableRequiredServices` for the - same reason as the metrics pair above: a hive that is not the - service host is a *client* of this store, not a second one. + A hive that is not the service host is a *client* of this store, + not a second one. ''; }; @@ -167,14 +183,10 @@ in example = true; description = '' Run the swarm's secret store in a `swarm-bao` container on this - host. A swarm has one store and it has to exist somewhere, so - this is asserted from - {option}`services.hyperhive.swarm.enableRequiredServices` - alongside the other once-per-swarm services. + host. A swarm has one store and it has to exist somewhere. - That assertion is a `mkDefault`, which is what keeps *where* the - store runs a separate question from *that* it runs: set this - directly to put the store on a host of its own, and clients + *Where* it runs is a separate question from *that* it runs: set + this directly to put the store on a host of its own, and clients still reach it by name at {option}`services.hyperhive.swarm.bao.domain` rather than at a local address. @@ -193,9 +205,7 @@ in example = true; description = '' Run the swarm's authelia in a `swarm-authelia` container on this - host. {option}`services.hyperhive.swarm.enableRequiredServices` - turns this on — a swarm has one SSO provider, and that says it - lives here. + host. A swarm has one SSO provider, and this says it lives here. With it off, this hive is a *client*: {option}`services.hyperhive.swarm.authelia.url` still points at @@ -211,10 +221,8 @@ in description = '' Run the **swarm's** telemetry collector on this host. - Derives from - {option}`services.hyperhive.swarm.enableRequiredServices` with the - metrics pair it feeds: a swarm has one of these, and it belongs - wherever the shared services live rather than on every hive. + A swarm has one of these, and it belongs wherever the shared + services live rather than on every hive. Named `swarm-otel` rather than `otel` because there are two collectors and the tier is the whole distinction: @@ -233,10 +241,8 @@ in Run the swarm's matrix homeserver — matrix-tuwunel, in a `hive-matrix` container — on this host. - Derives from - {option}`services.hyperhive.swarm.enableRequiredServices` with - the other once-per-swarm services. Set it here directly to put - the homeserver somewhere other than the host holding the rest. + Set it directly to put the homeserver somewhere other than the + host holding the rest of the swarm's services. Client-side settings stay in {option}`services.hyperhive.swarm.matrix.*`, which every hive @@ -280,10 +286,8 @@ in Serve the swarm UI from this host. Derived from - {option}`services.hyperhive.deploy.swarm-controller.enable` rather - than from - {option}`services.hyperhive.swarm.enableRequiredServices`: the UI - is a view onto the controller's state and reaches it over that + {option}`services.hyperhive.deploy.swarm-controller.enable`: the + UI is a view onto the controller's state and reaches it over that daemon's unix socket, so the host that runs the controller is the host that can serve the UI. A hive that merely *uses* a swarm has nothing to serve here. diff --git a/nix/host-modules/hive-gateway/options.nix b/nix/host-modules/hive-gateway/options.nix index f0199342..010c96b5 100644 --- a/nix/host-modules/hive-gateway/options.nix +++ b/nix/host-modules/hive-gateway/options.nix @@ -92,7 +92,7 @@ in DNS shouldn't have a stale `/etc/hosts` entry sticking around. Requires `services.hyperhive.domain` to be set. - `services.hyperhive.enableAllLocalDefaults` turns this on as + `services.hyperhive.deploy.singleHostSwarm` turns this on as part of saying "this box is the whole deployment": that mode means there is no real DNS for these names and the operator is browsing them from the host itself. Set it here explicitly to diff --git a/nix/host-modules/hyperhive.nix b/nix/host-modules/hyperhive.nix index 4cec58ce..b6d177d2 100644 --- a/nix/host-modules/hyperhive.nix +++ b/nix/host-modules/hyperhive.nix @@ -170,7 +170,7 @@ in ''; }; - # `enableAllLocalDefaults` is declared in ./local-defaults.nix, with + # `singleHostSwarm` is declared in ./local-defaults.nix, with # the values it asserts. It is a deployment mode rather than a setting # this module's options read, so it lives with its consequences. diff --git a/nix/host-modules/local-defaults.nix b/nix/host-modules/local-defaults.nix index 5034eee5..528f86de 100644 --- a/nix/host-modules/local-defaults.nix +++ b/nix/host-modules/local-defaults.nix @@ -1,6 +1,6 @@ # The all-local deployment mode. # -# `enableAllLocalDefaults` is a *mode*, not a default other options read: +# `singleHostSwarm` is a *mode*, not a default other options read: # it says "this box is the whole deployment" and then asserts the values # that follow from that. mara, on the issue: it is "more of a deployment # mode via settings set, less a default setting". @@ -23,7 +23,7 @@ let cfg = config.services.hyperhive; in { - options.services.hyperhive.enableAllLocalDefaults = lib.mkOption { + options.services.hyperhive.deploy.singleHostSwarm = lib.mkOption { type = lib.types.bool; default = false; example = true; @@ -31,7 +31,7 @@ in Run the whole swarm on this host. Turning this on asserts the toggles that an all-on-one-box deployment implies: the swarm's shared services - (`services.hyperhive.swarm.enableRequiredServices`), the swarm + (`services.hyperhive.deploy.allSwarmServices`), the swarm CA (`services.hyperhive.swarm.ca.autoConfigure`), the swarm controller (`services.hyperhive.deploy.swarm-controller.enable`), and the host's `/etc/hosts` entries for the names this hive serves @@ -69,17 +69,23 @@ in # every agent at its own netns. That guard already existing is what # makes turning this on by default safe; without it this line would # break every agent's access to the forge. - config.services.hyperhive.gateway.localHostsEntry = lib.mkDefault cfg.enableAllLocalDefaults; + config.services.hyperhive.gateway.localHostsEntry = lib.mkDefault cfg.deploy.singleHostSwarm; + + # Out of the `swarm` attrset below, because it is a `deploy.*` option now + # (./deploy.nix): "does THIS host run the swarm's services" is a per-host + # decision. Written as a path rather than folded into a second + # `config.services.hyperhive.deploy = { … }` attrset, for the same reason + # the ⚠️ below gives about `swarm`. + config.services.hyperhive.deploy.allSwarmServices = lib.mkDefault cfg.deploy.singleHostSwarm; config.services.hyperhive.swarm = { - enableRequiredServices = lib.mkDefault cfg.enableAllLocalDefaults; - ca.autoConfigure = lib.mkDefault cfg.enableAllLocalDefaults; + ca.autoConfigure = lib.mkDefault cfg.deploy.singleHostSwarm; # The queue's auth-callout nkeys. Generating them is safe exactly # when one operator owns both the queue and its responder, which is # what this mode asserts. On any other topology the seeds have to # reach whoever runs the responder, and minting them here would move # that hand-off somewhere less visible rather than removing it. - nats.autoGenerateCallout = lib.mkDefault cfg.enableAllLocalDefaults; + nats.autoGenerateCallout = lib.mkDefault cfg.deploy.singleHostSwarm; # The controller's queue coordinates. Co-location is what makes these # derivable at all — loopback only reaches the queue when the queue is # here, and the minted client secret only exists on the host authelia @@ -101,10 +107,10 @@ in # The *requirement* stays in `swarm-controller.nix` as an assertion: # needing a queue is the controller's own property in every topology, # and only the convenience is local. - controller.queue.natsUrl = lib.mkIf cfg.enableAllLocalDefaults ( + controller.queue.natsUrl = lib.mkIf cfg.deploy.singleHostSwarm ( lib.mkDefault "nats://127.0.0.1:${toString config.services.hyperhive.swarm.nats.port}" ); - controller.queue.clientSecretFile = lib.mkIf cfg.enableAllLocalDefaults ( + controller.queue.clientSecretFile = lib.mkIf cfg.deploy.singleHostSwarm ( lib.mkDefault "${config.services.hyperhive.swarm.authelia.hostClientSecretDir}/swarm-controller.secret" ); }; @@ -113,7 +119,7 @@ in # option stays `default = false` precisely because running it is a # statement about swarm topology — but "this box is the whole # deployment" IS that statement, and it is the one shape where the - # answer isn't ambiguous. Deriving it from `enableRequiredServices` + # answer isn't ambiguous. Deriving it from `allSwarmServices` # instead would be wrong: a hive in a larger swarm can legitimately # want the shared services without being the host that controls them. # @@ -122,5 +128,5 @@ in # the per-host fact `swarm.*` may not carry. The ⚠️ collision note above # does not apply here — that one is about two definitions of `swarm` # itself, and this is a different top-level path. - config.services.hyperhive.deploy.swarm-controller.enable = lib.mkDefault cfg.enableAllLocalDefaults; + config.services.hyperhive.deploy.swarm-controller.enable = lib.mkDefault cfg.deploy.singleHostSwarm; } diff --git a/nix/host-modules/swarm-authelia.nix b/nix/host-modules/swarm-authelia.nix index 4c8ba9e7..93a63e71 100644 --- a/nix/host-modules/swarm-authelia.nix +++ b/nix/host-modules/swarm-authelia.nix @@ -6,7 +6,7 @@ # - the CLIENT pointer (`url`) exists on every hive, because a hive # that doesn't run authelia still has to know where to send people. # - the CONTAINER only exists where the swarm's shared services live. -# `swarm.enableRequiredServices` asserts this module's `enable` +# `deploy.allSwarmServices` asserts this module's `enable` # (see ./swarm-required-services.nix); a hive is a client by default. # # Operator and agents are both subjects of the same provider, @@ -992,7 +992,7 @@ in # # Gated on the collector's `enable` as well, and that second condition is # what makes the loopback address honest. Both services default from - # `swarm.enableRequiredServices` — but `mkDefault` is an invitation to + # `deploy.allSwarmServices` — but `mkDefault` is an invitation to # override, not a guarantee, so "they are on the same host" is a property # of the auto-deployed topology rather than of the module. Without this # gate, a host running authelia and no collector would declare a target diff --git a/nix/host-modules/swarm-ca.nix b/nix/host-modules/swarm-ca.nix index d522ae57..f4d5c8cd 100644 --- a/nix/host-modules/swarm-ca.nix +++ b/nix/host-modules/swarm-ca.nix @@ -11,7 +11,7 @@ # Two provisioning modes, ONE structure — what differs is who puts the # artifacts on disk, never what the artifacts are: # -# - autoconfigured (`services.hyperhive.enableAllLocalDefaults`, or +# - autoconfigured (`services.hyperhive.deploy.singleHostSwarm`, or # `autoConfigure` set directly): the unit below generates the root # here on first boot. # - operator-provided (multi-host): the operator installs the root cert @@ -68,7 +68,7 @@ in 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. - `services.hyperhive.enableAllLocalDefaults` turns this on as + `services.hyperhive.deploy.singleHostSwarm` turns this on as part of the all-on-one-box mode. Set it here directly to run the CA on a host that is not otherwise all-local. diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index fbc5a3f3..b54686ba 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -240,7 +240,7 @@ in }; # `enable` moved to `services.hyperhive.deploy.swarm-controller.enable` — see - # ./deploy.nix. `services.hyperhive.enableAllLocalDefaults` still + # ./deploy.nix. `services.hyperhive.deploy.singleHostSwarm` still # asserts it, and that was never an exception to "not derived from # services.hyperhive.enable": that mode says "this box is the whole # deployment", which answers the topology question outright, where @@ -320,7 +320,7 @@ in Empty means unset, which the assertion below refuses — a controller with no queue is not a lighter controller. - `enableAllLocalDefaults` fills this in with loopback, because + `singleHostSwarm` fills this in with loopback, because that address is only correct when the queue is on this host: its container shares the host netns. That derivation lives with the mode rather than here, so this option describes itself @@ -354,7 +354,7 @@ in The controller cannot mint its own — minting happens inside authelia's state directory during its first boot — so away from that host the operator places the secret and names it here. - `enableAllLocalDefaults` points this at the minted file, which + `singleHostSwarm` points this at the minted file, which is exactly the case where one exists locally. Read by `LoadCredential`, so it needs to be readable by root at diff --git a/nix/host-modules/swarm-nats.nix b/nix/host-modules/swarm-nats.nix index 8e98cac2..e5266cb4 100644 --- a/nix/host-modules/swarm-nats.nix +++ b/nix/host-modules/swarm-nats.nix @@ -297,7 +297,7 @@ in Leave it off wherever the queue and its clients are not the same operator's problem: the seeds must reach whoever runs the responder, and minting them here only moves that distribution - somewhere less visible. `enableAllLocalDefaults` turns it on. + somewhere less visible. `singleHostSwarm` turns it on. ''; }; diff --git a/nix/host-modules/swarm-required-services.nix b/nix/host-modules/swarm-required-services.nix index a3c649f5..bc57d663 100644 --- a/nix/host-modules/swarm-required-services.nix +++ b/nix/host-modules/swarm-required-services.nix @@ -4,20 +4,20 @@ # where they live, and asserts the per-service `enable`s that follow — # the same mode-not-default shape as ./local-defaults.nix, one tier down. # -# Only the *optional* services derive: matrix and authelia. The forge has -# no `enable` to assert, because it is not optional — it is the canonical -# store for the meta flake and every agent's config repo, so it deploys -# with hyperhive itself. +# Only the *optional* services derive. The forge has no `enable` to +# assert, because it is not optional — it is the canonical store for the +# meta flake and every agent's config repo, so it deploys with hyperhive +# itself. { lib, config, ... }: let - swarmCfg = config.services.hyperhive.swarm; + deployCfg = config.services.hyperhive.deploy; in { - options.services.hyperhive.swarm.enableRequiredServices = lib.mkOption { + options.services.hyperhive.deploy.allSwarmServices = lib.mkOption { type = lib.types.bool; default = false; example = true; @@ -28,15 +28,16 @@ in and log stores — have their toggle asserted from this, so a swarm's service host is declared in one place. - Those toggles live in two namespaces and the split is deliberate: - {option}`services.hyperhive.deploy.*` for "does THIS host run it", - `swarm.*.enable` for the ones not yet moved. See ./deploy.nix. + Every toggle it asserts is a {option}`services.hyperhive.deploy.*` + one, because "does THIS host run it" is a per-host decision — which + is the same reason this option is a `deploy.*` one itself. See + ./deploy.nix. The forge is swarm-wide too but has nothing to assert: it is the canonical store for the meta flake and every agent's config repo, so it deploys with hyperhive itself and is not optional. - `services.hyperhive.enableAllLocalDefaults` turns this on as part + `services.hyperhive.deploy.singleHostSwarm` turns this on as part of the all-on-one-box mode. Set it directly to run the swarm's services on a host that is not otherwise all-local — a dedicated services box with hives elsewhere is exactly that shape. @@ -52,49 +53,44 @@ in # Everything derives under `deploy.*` now, because "does THIS host run # it" is a per-host decision and `swarm.*` has to be identical on every # host. Same switch, same rule, one attribute path. - config.services.hyperhive.deploy.matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.matrix.enable = lib.mkDefault deployCfg.allSwarmServices; # The collector that feeds the pair above (note: no `swarm.` prefix, # this is ./otel.nix's existing per-hive option). - config.services.hyperhive.otel.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.otel.enable = lib.mkDefault deployCfg.allSwarmServices; - # The rest of the shared services, deriving from the same switch as the - # `swarm.*` ones above. They read differently only because "does THIS - # host run it" lives in `deploy.*` (./deploy.nix) — `swarm.*` has to be - # identical on every host, and these are exactly the values that must - # differ. + # The rest of the shared services, from the same switch and for the same + # reason. # # authelia: a swarm has one SSO provider, and this says it lives here. # With it off the hive is a *client* — `swarm.authelia.url` still points # at whoever runs it. - config.services.hyperhive.deploy.authelia.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.authelia.enable = lib.mkDefault deployCfg.allSwarmServices; # The queue. Same rule: once per swarm, optional. - config.services.hyperhive.deploy.nats.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.nats.enable = lib.mkDefault deployCfg.allSwarmServices; # The swarm collector that feeds the metrics pair, and the only tier # holding the upstream credential. ⚠️ NOT the per-hive collector below, # which every hive runs. - config.services.hyperhive.deploy.swarm-otel.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.swarm-otel.enable = lib.mkDefault deployCfg.allSwarmServices; # The metrics pair, deriving together on purpose: a store with no UI is # unreadable and a UI with no store is empty, so there is no sensible # deployment that takes one and not the other from this switch. An # operator who wants exactly one still sets it directly, which # `mkDefault` allows. - config.services.hyperhive.deploy.victoriametrics.enable = - lib.mkDefault swarmCfg.enableRequiredServices; - config.services.hyperhive.deploy.grafana.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.victoriametrics.enable = lib.mkDefault deployCfg.allSwarmServices; + config.services.hyperhive.deploy.grafana.enable = lib.mkDefault deployCfg.allSwarmServices; # The log store, from the same switch for the same reason as the rest: a # hive that is not the service host is a *client* of it, not a second one. - config.services.hyperhive.deploy.victorialogs.enable = - lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.victorialogs.enable = lib.mkDefault deployCfg.allSwarmServices; # The secret store. Once per swarm and optional, so it belongs to the # same switch: a hive that does not run it is a *client*, reading its # own secrets from whoever does. `mkDefault` is what keeps the store # placeable on a host of its own — it can be set directly here and # turned off wherever this switch happens to be on. - config.services.hyperhive.deploy.bao.enable = lib.mkDefault swarmCfg.enableRequiredServices; + config.services.hyperhive.deploy.bao.enable = lib.mkDefault deployCfg.allSwarmServices; } diff --git a/nix/host-modules/swarm.nix b/nix/host-modules/swarm.nix index 9bedc776..2fd9d961 100644 --- a/nix/host-modules/swarm.nix +++ b/nix/host-modules/swarm.nix @@ -80,11 +80,11 @@ let # ONE condition for all three of them, deliberately. # # 🩸 They were three independent conditions first, and that was wrong in - # a way only an eval gate finds: at the time `enableRequiredServices` + # a way only an eval gate finds: at the time `allSwarmServices` # turned on matrix and authelia but NOT nats, so an ordinary all-local # hive resolved authelia's two coordinates and not the queue URL. Two of # three set is exactly what the assertion below rejects, so every - # `enableAllLocalDefaults` hive would have stopped evaluating. + # `singleHostSwarm` hive would have stopped evaluating. # # (The queue does derive from that switch now — ./swarm-required-services.nix # — so the original asymmetry is gone. The reasoning below is why the @@ -382,7 +382,7 @@ in ]; }; - # `enableRequiredServices` is declared in ./swarm-required-services.nix + # `allSwarmServices` is declared in ./swarm-required-services.nix # together with the per-service `enable`s it asserts — it is a # deployment-shape switch rather than swarm bookkeeping, so it lives # with its consequences instead of here. diff --git a/nix/module-eval.nix b/nix/module-eval.nix index 67b8b5e5..ebc36bee 100644 --- a/nix/module-eval.nix +++ b/nix/module-eval.nix @@ -67,7 +67,7 @@ let ]; }).config; - allLocal = hive { enableAllLocalDefaults = true; }; + allLocal = hive { deploy.singleHostSwarm = true; }; bare = hive { }; withCi = hive { deploy.forgejo.ci.enable = true; };