swarm: move the matrix packages to deploy, where their enable already lives

Which build a service runs is a decision of the host that runs it, so
`*.package` belongs with `enable` rather than in the namespace every hive
must agree on byte for byte.

The `gui` pair was the sharpest case and the reason this starts here:
`gui.enable` moved to `deploy.*` in an earlier slice while `gui.package`
stayed behind, so one web client's two halves sat in two namespaces —
and hive-matrix.nix said so, in a comment directly above the option.
The diff removes a stated inconsistency rather than introducing a rule.

Both old paths keep working through `mkRenamedOptionModule`; both are
settable (neither is `readOnly`), so both get a shim. The `matrixOldPath`
fixture in module-eval.nix now sets eight options through their
pre-rename paths instead of six, so dropping either new shim fails the
eval rather than silently dropping a definition.

Prose swept in the same commit: three comments claimed the package was
swarm-wide or named the pre-rename path, and docs/web-ui/dashboard.md
named `swarm.matrix.gui.package` two lines above
`deploy.matrix.gui.enable` — the same asymmetry this commit exists to
remove, displayed in the docs. A shim keeps the old spelling valid, so
no build, lint or broken-reference search would have found that line.

Refs #3772.
This commit is contained in:
atlas 2026-09-07 18:35:34 +02:00
commit d6f23ff371
4 changed files with 61 additions and 46 deletions

View file

@ -625,7 +625,7 @@ existing in the page DOM.
A static matrix web client (default `pkgs.fluffychat-web` rebuilt
with `--base-href /matrix/`, swappable via
`services.hyperhive.swarm.matrix.gui.package`) served by the hive-gateway
`services.hyperhive.deploy.matrix.gui.package`) served by the hive-gateway
nginx container at `/matrix/` when
`services.hyperhive.deploy.matrix.gui.enable` is on (defaults to
`matrix.enable`). c0re signals availability via the

View file

@ -335,6 +335,20 @@ in
[ "services" "hyperhive" "swarm" "wireguard" "persistentKeepalive" ]
[ "services" "hyperhive" "deploy" "wireguard" "persistentKeepalive" ]
)
# Which build a service runs is a decision of the host that runs it, so
# every `*.package` follows its `enable` across. The split these replace
# was the sharpest case: `gui.enable` had already moved while
# `gui.package` stayed, so one client's two halves sat in two namespaces
# and ./hive-matrix.nix said so in a comment above the option.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "swarm" "matrix" "package" ]
[ "services" "hyperhive" "deploy" "matrix" "package" ]
)
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "swarm" "matrix" "gui" "package" ]
[ "services" "hyperhive" "deploy" "matrix" "gui" "package" ]
)
];
# ⚠️ `deploy.forgejo` is declared in ./hive-ci.nix, not here, and it is the

View file

@ -172,8 +172,9 @@ in
[ "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.
# namespace every host in the swarm agrees on. What stays under
# `swarm.matrix` is the homeserver's identity as every hive sees it —
# its server name, its addresses, its federation policy.
(lib.mkRenamedOptionModule
[ "services" "hyperhive" "swarm" "matrix" "enable" ]
[ "services" "hyperhive" "deploy" "matrix" "enable" ]
@ -191,17 +192,6 @@ in
];
options.services.hyperhive.swarm.matrix = {
package = lib.mkOption {
type = lib.types.package;
default = pkgs.matrix-tuwunel;
defaultText = lib.literalExpression "pkgs.matrix-tuwunel";
description = ''
matrix-tuwunel package to run inside the container. Defaults
to nixpkgs's `pkgs.matrix-tuwunel`. Override to pin a
specific upstream if you need an unreleased feature.
'';
};
serverName = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
@ -338,26 +328,6 @@ in
'';
};
gui = {
# Whether this host serves it is `deploy.matrix.gui.enable`.
package = lib.mkOption {
type = lib.types.package;
default = fluffychat-web-fixed;
defaultText = lib.literalMD ''
`pkgs.fluffychat-web` with a `postInstall` patch that adds
the three files `flutter341.buildFlutterApplication` skips.
'';
description = ''
Static web client dist served at `gatewayHost`'s vhost
(`chat.<swarm-domain>` by default). Override
to swap fluffychat for hydrogen-web, cinny, element-web, or
an out-of-tree dist any replacement is mounted at the
sub-domain root with the upstream-default `<base href "/">`,
no sub-path gymnastics needed.
'';
};
};
# This homeserver always delegates login to the swarm's authelia, as
# an OIDC relying party — matrix SSO (`m.login.sso`), offered
# alongside password login. No toggle: a homeserver in a swarm is a
@ -398,13 +368,24 @@ in
};
# What stays above is what the homeserver IS from any hive's point of view:
# its package, the name it answers to, the ports and URLs it is reached on,
# and the client id it is registered under. What lives here is what the host
# running it decides — whether it is exposed, which peers it trusts, how large
# a request it accepts, and where its host-local secrets sit. Same rule as
# the name it answers to, the ports and URLs it is reached on, and the client
# id it is registered under. What lives here is what the host running it
# decides — which build it runs, whether it is exposed, which peers it trusts,
# how large a request it accepts, and where its host-local secrets sit. Same rule as
# ./swarm-victorialogs.nix; `enable` already lives in ./deploy.nix, which also
# carries the renames.
options.services.hyperhive.deploy.matrix = {
package = lib.mkOption {
type = lib.types.package;
default = pkgs.matrix-tuwunel;
defaultText = lib.literalExpression "pkgs.matrix-tuwunel";
description = ''
matrix-tuwunel package to run inside the container. Defaults
to nixpkgs's `pkgs.matrix-tuwunel`. Override to pin a
specific upstream if you need an unreleased feature.
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
@ -509,11 +490,28 @@ in
off, the dashboard's `M4TR1X ` tab is hidden. See
`docs/networking/gateway.md` for the discovery flow that lets clients
auto-find the sub-domain. The client build itself is
`swarm.matrix.gui.package` which client, as opposed to whether
`deploy.matrix.gui.package` which client, as opposed to whether
this host serves it.
'';
};
gui.package = lib.mkOption {
type = lib.types.package;
default = fluffychat-web-fixed;
defaultText = lib.literalMD ''
`pkgs.fluffychat-web` with a `postInstall` patch that adds
the three files `flutter341.buildFlutterApplication` skips.
'';
description = ''
Static web client dist served at `gatewayHost`'s vhost
(`chat.<swarm-domain>` by default). Override
to swap fluffychat for hydrogen-web, cinny, element-web, or
an out-of-tree dist any replacement is mounted at the
sub-domain root with the upstream-default `<base href "/">`,
no sub-path gymnastics needed.
'';
};
sso.clientSecretFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
@ -634,7 +632,7 @@ in
# fluffychat at sub-domain root, SPA-fallback via the
# Accept-header `$matrix_spa_target` map above.
"/" = {
alias = "${cfg.gui.package}/";
alias = "${deployCfg.matrix.gui.package}/";
extraConfig = ''
try_files $uri $uri/ $matrix_spa_target =404;
'';
@ -999,7 +997,7 @@ in
services.matrix-tuwunel = {
enable = true;
package = cfg.package;
package = deployCfg.matrix.package;
settings.global = {
server_name = effectiveServerName;
# `address` + `port` are upstream `listOf` — wrap singles.
@ -1084,7 +1082,7 @@ in
"oidc_client_secret:${toString deployCfg.matrix.sso.clientSecretFile}"
];
environment.systemPackages = [ cfg.package ];
environment.systemPackages = [ deployCfg.matrix.package ];
};
};

View file

@ -89,11 +89,12 @@ let
];
};
# The homeserver's turn to split. All six host-side options are set through
# The homeserver's turn to split. All eight host-side options are set through
# their pre-rename paths — including `gui.enable`, whose value is deliberately
# the opposite of its default so the definition has to actually land. All six
# so that dropping any single shim entry fails the eval, not just the two the
# assertion reads.
# the opposite of its default so the definition has to actually land, and both
# packages, stubbed to a derivation neither option defaults to for the same
# reason. All eight so that dropping any single shim entry fails the eval, not
# just the ones the assertions read.
matrixOldPath = hive {
deploy.matrix.enable = true;
swarm.matrix.openFirewall = true;
@ -101,6 +102,8 @@ let
swarm.matrix.maxRequestSize = 31457280;
swarm.matrix.registrationTokenFile = "/etc/matrix/register.token";
swarm.matrix.gui.enable = false;
swarm.matrix.package = pkgs.emptyDirectory;
swarm.matrix.gui.package = pkgs.emptyDirectory;
swarm.matrix.sso.clientSecretFile = "/etc/matrix/oidc.secret";
};