diff --git a/docs/tools/hivectl.md b/docs/tools/hivectl.md index a8d502c2..7f7b5d76 100644 --- a/docs/tools/hivectl.md +++ b/docs/tools/hivectl.md @@ -58,7 +58,7 @@ hivectl forge reconcile-config iris --verbose # include the full diff, not Manual entry to the same idempotent matrix provisioning flow `hive-c0re` runs at boot. Requires the `hive-matrix` container to be -running (`services.hyperhive.swarm.matrix.enable = true`). +running (`services.hyperhive.deploy.matrix.enable = true`). ```bash hivectl matrix create-user iris # provision (or re-provision) matrix account for agent `iris` diff --git a/hive-c0re/src/matrix.rs b/hive-c0re/src/matrix.rs index d524e0ce..dd08459b 100644 --- a/hive-c0re/src/matrix.rs +++ b/hive-c0re/src/matrix.rs @@ -1,7 +1,7 @@ //! Optional matrix-tuwunel wiring: shared registration token (host) + //! per-agent UIAA registration → `/matrix-token`. No-op //! when the `hive-matrix` container isn't running, so operators who -//! haven't flipped `services.hyperhive.swarm.matrix.enable = true` pay +//! haven't flipped `services.hyperhive.deploy.matrix.enable = true` pay //! nothing. //! //! See `docs/matrix.md::Provisioning flow (registration token)` for diff --git a/hive-c0re/src/server.rs b/hive-c0re/src/server.rs index 2a469429..85a80cde 100644 --- a/hive-c0re/src/server.rs +++ b/hive-c0re/src/server.rs @@ -487,7 +487,7 @@ fn require_matrix_present() -> Result<()> { return Ok(()); } anyhow::bail!( - "no matrix homeserver configured — set services.hyperhive.swarm.matrix.enable = true to run one \ + "no matrix homeserver configured — set services.hyperhive.deploy.matrix.enable = true to run one \ here, or services.hyperhive.swarm.matrix.apiUrl to point at an existing one, before \ provisioning matrix users" ) diff --git a/nix/docs/default.nix b/nix/docs/default.nix index ec1836df..3d809600 100644 --- a/nix/docs/default.nix +++ b/nix/docs/default.nix @@ -54,7 +54,7 @@ let boot.loader.grub.enable = false; system.stateVersion = "25.11"; services.hyperhive.enable = lib.mkForce false; - services.hyperhive.swarm.matrix.enable = lib.mkForce false; + services.hyperhive.deploy.matrix.enable = lib.mkForce false; } ) ]; diff --git a/nix/host-modules/deploy.nix b/nix/host-modules/deploy.nix index 8ae9ae71..e4020c0b 100644 --- a/nix/host-modules/deploy.nix +++ b/nix/host-modules/deploy.nix @@ -152,6 +152,24 @@ in ''; }; + matrix.enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + 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. + + Client-side settings stay in + {option}`services.hyperhive.swarm.matrix.*`, which every hive + agrees on; this is only the decision to run it here. + ''; + }; + nats.enable = lib.mkOption { type = lib.types.bool; default = false; diff --git a/nix/host-modules/hive-c0re/environment.nix b/nix/host-modules/hive-c0re/environment.nix index c1df0c6e..11088fc3 100644 --- a/nix/host-modules/hive-c0re/environment.nix +++ b/nix/host-modules/hive-c0re/environment.nix @@ -162,7 +162,7 @@ in // lib.optionalAttrs ( - config.services.hyperhive.swarm.matrix.enable + config.services.hyperhive.deploy.matrix.enable && config.services.hyperhive.swarm.matrix.gatewayHost != null ) { diff --git a/nix/host-modules/hive-matrix.nix b/nix/host-modules/hive-matrix.nix index 8084f380..8d1d33bd 100644 --- a/nix/host-modules/hive-matrix.nix +++ b/nix/host-modules/hive-matrix.nix @@ -164,6 +164,13 @@ in [ "services" "hyperhive" "matrix" ] [ "services" "hyperhive" "swarm" "matrix" ] ) + # "does THIS host run it" is a per-host decision, and `swarm.*` is the + # namespace every host in the swarm agrees on. The rest of the matrix + # settings genuinely are swarm-wide and stay where they are. + (lib.mkRenamedOptionModule + [ "services" "hyperhive" "swarm" "matrix" "enable" ] + [ "services" "hyperhive" "deploy" "matrix" "enable" ] + ) (lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "sso" "enable" ] '' SSO is no longer optional: a homeserver that runs at all delegates login to the swarm's authelia. @@ -177,21 +184,6 @@ in ]; options.services.hyperhive.swarm.matrix = { - enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Run hive-matrix — a private matrix-tuwunel homeserver (in a - nixos-container) for hyperhive agents. - - Matrix is a swarm-wide service — one homeserver, not one per - hive — so `services.hyperhive.swarm.enableRequiredServices` - turns this on as part of saying the swarm's shared services live - on this host. Set it here directly to run the homeserver - somewhere other than the host that holds the rest of them. - ''; - }; - package = lib.mkOption { type = lib.types.package; default = pkgs.matrix-tuwunel; @@ -254,9 +246,9 @@ in apiUrl = lib.mkOption { type = lib.types.nullOr lib.types.str; - default = if cfg.enable then "http://127.0.0.1:${toString cfg.httpPort}" else null; + default = if deployCfg.matrix.enable then "http://127.0.0.1:${toString cfg.httpPort}" else null; defaultText = lib.literalExpression '' - if services.hyperhive.swarm.matrix.enable + if services.hyperhive.deploy.matrix.enable then "http://127.0.0.1:''${toString services.hyperhive.swarm.matrix.httpPort}" else null ''; @@ -411,8 +403,8 @@ in gui = { enable = lib.mkOption { type = lib.types.bool; - default = cfg.enable; - defaultText = lib.literalExpression "config.services.hyperhive.swarm.matrix.enable"; + default = deployCfg.matrix.enable; + defaultText = lib.literalExpression "config.services.hyperhive.deploy.matrix.enable"; description = '' Serve a matrix web client at `matrix.''${services.hyperhive.domain}/`. Requires `matrix.gatewayHost != null` (default `matrix.` @@ -498,7 +490,7 @@ in }; }; - config = lib.mkIf cfg.enable { + config = lib.mkIf deployCfg.matrix.enable { # Matrix's own gateway surface: the sub-domain vhost, the name the # hive resolver answers for, and the Accept-header map that vhost's # SPA fallback reads. All three are matrix knowledge and none of diff --git a/nix/host-modules/swarm-required-services.nix b/nix/host-modules/swarm-required-services.nix index 8e8e5fc1..c69eeaff 100644 --- a/nix/host-modules/swarm-required-services.nix +++ b/nix/host-modules/swarm-required-services.nix @@ -48,15 +48,11 @@ in # Same precedence reasoning as ./local-defaults.nix: fills in for an # operator who hasn't spoken, yields to one who has. - config.services.hyperhive.swarm = { - # The last one still spelled `swarm.*.enable`. Everything else that - # used to derive here — the queue, the SSO provider, the collector, - # the metrics pair, the log store — now derives below under - # `deploy.*`, because "does THIS host run it" is a per-host decision - # and `swarm.*` has to be identical on every host. Same switch, same - # rule, different attribute path. - matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices; - }; + # + # 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; # The collector that feeds the pair above (note: no `swarm.` prefix, # this is ./otel.nix's existing per-hive option).