diff --git a/nix/host-modules/default.nix b/nix/host-modules/default.nix index dab30a4d..5057dd0c 100644 --- a/nix/host-modules/default.nix +++ b/nix/host-modules/default.nix @@ -53,6 +53,7 @@ ./swarm-otel.nix ./swarm-snapshot-store.nix ./swarm-ui.nix + ./swarm-victorialogs-service.nix ./swarm-victorialogs.nix ./swarm-victoriametrics-service.nix ./swarm-victoriametrics.nix diff --git a/nix/host-modules/swarm-victorialogs-service.nix b/nix/host-modules/swarm-victorialogs-service.nix new file mode 100644 index 00000000..f59936f4 --- /dev/null +++ b/nix/host-modules/swarm-victorialogs-service.nix @@ -0,0 +1,66 @@ +# The swarm's log store as every hive sees it: the name it answers on and its +# port, identical on every host. What the host running it decides, and the +# container itself, are in ./swarm-victorialogs.nix. +{ + lib, + config, + ... +}: +let + hyperhiveCfg = config.services.hyperhive; + swarmDomain = hyperhiveCfg.swarm.domain; + + # Total on a null swarm domain for the same reason every sibling module is: + # the required-domain assertion in hive-network.nix should be what an + # operator sees, not a coercion error from here. + domainBase = if swarmDomain == null then "invalid" else swarmDomain; +in +{ + # What the store IS from any hive's point of view: the name it answers on and + # the port. `enable`, `package` and `retentionPeriod` are decisions of the + # host that runs it and live under `deploy.*`. + options.services.hyperhive.swarm.victorialogs = { + machine = lib.mkOption { + type = lib.types.str; + readOnly = true; + default = "swarm-victorialogs"; + description = '' + Container name. Read-only: the name appears in host paths and in + `machinectl`, so it is a fact other modules may read rather than a + knob. + ''; + }; + + domain = lib.mkOption { + type = lib.types.str; + default = "logs.${domainBase}"; + defaultText = lib.literalExpression ''"logs.''${services.hyperhive.swarm.domain}"''; + description = '' + Name the gateway serves this on, behind the same authelia + `auth_request` gate as the swarm UI's own vhost. A sibling of the + swarm's other service names, so the swarm-services sub-CA can + issue for it — see `hive-tls.nix` for why a service name being a + sibling rather than a child decides which CA may sign it, and + `swarm.nix`'s `serviceDomains'` for where this name has to be + registered for that to actually happen. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 9428; + description = '' + Loopback port the store listens on. Upstream's default, kept + because there is no reason to move it and a familiar number is + one less thing an operator has to look up. + + ⚠️ Every swarm container shares the host's network namespace, so + this is a swarm-wide claim rather than a per-container one — two + modules picking the same number collide at runtime with no bind + error and nothing in any log. `state/eval-port-collisions.sh` + checks the class. + ''; + }; + + }; +} diff --git a/nix/host-modules/swarm-victorialogs.nix b/nix/host-modules/swarm-victorialogs.nix index 408876c2..a295fd21 100644 --- a/nix/host-modules/swarm-victorialogs.nix +++ b/nix/host-modules/swarm-victorialogs.nix @@ -40,12 +40,6 @@ let networkCfg = config.services.hyperhive.network; hyperhiveCfg = config.services.hyperhive; gatewayCfg = hyperhiveCfg.gateway; - swarmDomain = hyperhiveCfg.swarm.domain; - - # Total on a null swarm domain for the same reason every sibling module is: - # the required-domain assertion in hive-network.nix should be what an - # operator sees, not a coercion error from here. - domainBase = if swarmDomain == null then "invalid" else swarmDomain; # Copy of `swarm-ui.nix`'s own `swarmAuthRequest` — not shared code because # this vhost needs exactly the two locations that reference it (`/` and the @@ -63,54 +57,10 @@ let privateNetwork = false; in { - # What stays here is what the store IS from any hive's point of view: the - # name it answers on and the port. `enable`, `package` and - # `retentionPeriod` are decisions of the host that runs it and live under - # `deploy.*`. - options.services.hyperhive.swarm.victorialogs = { - machine = lib.mkOption { - type = lib.types.str; - readOnly = true; - default = "swarm-victorialogs"; - description = '' - Container name. Read-only: the name appears in host paths and in - `machinectl`, so it is a fact other modules may read rather than a - knob. - ''; - }; - - domain = lib.mkOption { - type = lib.types.str; - default = "logs.${domainBase}"; - defaultText = lib.literalExpression ''"logs.''${services.hyperhive.swarm.domain}"''; - description = '' - Name the gateway serves this on, behind the same authelia - `auth_request` gate as the swarm UI's own vhost. A sibling of the - swarm's other service names, so the swarm-services sub-CA can - issue for it — see `hive-tls.nix` for why a service name being a - sibling rather than a child decides which CA may sign it, and - `swarm.nix`'s `serviceDomains'` for where this name has to be - registered for that to actually happen. - ''; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 9428; - description = '' - Loopback port the store listens on. Upstream's default, kept - because there is no reason to move it and a familiar number is - one less thing an operator has to look up. - - ⚠️ Every swarm container shares the host's network namespace, so - this is a swarm-wide claim rather than a per-container one — two - modules picking the same number collide at runtime with no bind - error and nothing in any log. `state/eval-port-collisions.sh` - checks the class. - ''; - }; - - }; + # What the store IS from any hive's point of view, the name it answers on and + # the port, is `swarm.victorialogs` in ./swarm-victorialogs-service.nix. + # `enable`, `package` and `retentionPeriod` are decisions of the host that + # runs it and live under `deploy.*`. # Retention is a property of the store this host runs, not something the # swarm has to agree on: it is read only where the container is defined,