From 3fc7a785fad9e4451b2b162d9a1dee69da15dee7 Mon Sep 17 00:00:00 2001 From: atlas Date: Sun, 27 Sep 2026 14:42:58 +0200 Subject: [PATCH] swarm-controller: default matrixHomeserverUrl from swarm.matrix.gatewayHost matrixHomeserverUrl re-derived gatewayHost's own default (chat.${swarmDomain}) instead of reading gatewayHost itself, so a deployment that pins gatewayHost away from that default (the exact case hive-matrix.nix's own option doc describes) left the controller calling a name nothing serves. Read matrix.gatewayHost directly, mirroring hive-matrix.nix's ctlHomeserverUrl. Add module-eval cases that pin gatewayHost and that null it out, alongside the existing unpinned default case. Closes #4757 --- nix/host-modules/swarm-controller.nix | 11 +++++--- nix/module-eval/bao-controller.nix | 36 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index b89b47fb..6091d8d4 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -92,6 +92,7 @@ let forgeCfg = config.services.hyperhive.swarm.forge; swarmDomain = config.services.hyperhive.swarm.domain; + matrixCfg = config.services.hyperhive.swarm.matrix; # The controller's forge client speaks TLS to `https://${forgeCfg.domain}`, # which the gateway serves with a leaf signed by the hive CA — a CA @@ -558,10 +559,12 @@ in matrixHomeserverUrl = lib.mkOption { type = lib.types.nullOr lib.types.str; - # The same `chat.` ./hive-matrix.nix serves its vhost on - # (`gatewayHost`): a swarm runs one homeserver. - default = if swarmDomain == null then null else "https://chat.${swarmDomain}"; - defaultText = lib.literalExpression ''"https://chat.''${services.hyperhive.swarm.domain}"''; + # `gatewayHost`'s own vhost, not a re-derivation of its default: a + # deployment that pins `gatewayHost` (e.g. to keep a name from before + # it moved under the swarm domain) still has one homeserver, and this + # option has to name the same one. + default = if matrixCfg.gatewayHost == null then null else "https://${matrixCfg.gatewayHost}"; + defaultText = lib.literalExpression ''"https://''${services.hyperhive.swarm.matrix.gatewayHost}"''; example = "https://matrix.example.org"; description = '' Client-server API base of the swarm's homeserver. The controller diff --git a/nix/module-eval/bao-controller.nix b/nix/module-eval/bao-controller.nix index 671ee747..493c3923 100644 --- a/nix/module-eval/bao-controller.nix +++ b/nix/module-eval/bao-controller.nix @@ -45,6 +45,24 @@ let # files this host will never have. controllerNoStore = hive { deploy.swarm-controller.enable = true; }; + # A deployment that pinned `gatewayHost` away from its own swarm-domain + # default (`hive-matrix.nix`'s own doc: "a deployment that was running + # before this moved keeps its current name by pinning ... here"). Only + # this fixture can tell "the controller reads gatewayHost" apart from + # "the controller re-derives gatewayHost's default itself" — both render + # the same URL on every other fixture in this file. + controllerPinnedGateway = hive { + deploy.swarm-controller.enable = true; + swarm.matrix.gatewayHost = "matrix.hive.t.local"; + }; + + # No matrix vhost for this swarm at all: tuwunel stays direct on + # `httpPort`, so there is no homeserver URL to hand the controller. + controllerNoGatewayHost = hive { + deploy.swarm-controller.enable = true; + swarm.matrix.gatewayHost = null; + }; + # The two authorities told apart. A deployment that self-signs both ends # points `clientCaFile` and `serverCaFile` at one file, so on the fixture # above the CA a hive is issued from and the CA the store is verified by are @@ -77,6 +95,24 @@ let controllerNoStore.systemd.services.swarm-controller.environment.SWARM_CONTROLLER_MATRIX_HOMESERVER_URL or null == "https://chat.t.local"; } + { + # The case above alone can't tell "reads gatewayHost" from "re-derives + # gatewayHost's own default": both land on chat.t.local when nothing is + # pinned. This fixture pins gatewayHost away from that default, so only + # the former passes. + name = "the controller's homeserver follows a pinned gatewayHost, not its own chat. default"; + ok = + controllerPinnedGateway.systemd.services.swarm-controller.environment.SWARM_CONTROLLER_MATRIX_HOMESERVER_URL + or null == "https://matrix.hive.t.local"; + } + { + name = "a swarm with no matrix gateway vhost gives the controller no homeserver variable"; + ok = + !( + controllerNoGatewayHost.systemd.services.swarm-controller.environment + ? SWARM_CONTROLLER_MATRIX_HOMESERVER_URL + ); + } { # Nothing asserted the PKI script before this, so a third leaf could be # added to it and every case still passed — measured, not assumed: the