Watch
0
0
Fork
You've already forked hyperhive
0

Compare commits

...
Author SHA1 Message Date
atlas
e8813b86eb matrix: forward the homeserver URL from client hives too
HIVE_MATRIX_URL was conditioned on this host deploying the homeserver,
so a hive that is a client of the swarm's matrix forwarded nothing and
every agent's hive-matrix-daemon no-opped. hive-c0re already provisions
those agents' accounts against a remote homeserver through
HIVE_MATRIX_API_URL three lines below, whose gate is `apiUrl != null` —
it registered the users and then never told them where to log in.

gatewayHost is swarm-scoped and defaults to chat.<swarm-domain>, so it
names the swarm's one homeserver from any member hive. Its being set is
the real question, and a null swarm domain is already caught by the
assertion in hive-network.nix rather than by this expression.
2026-08-30 15:17:02 +02:00
atlas
2aa924d85a deploy: move the matrix homeserver toggle out of swarm
swarm.matrix.enable was the last toggle still spelled swarm.*, which
is the namespace every host in the swarm agrees on - and "does this
host run the homeserver" is exactly what differs between them. It
moves to deploy.matrix.enable with the rest; the genuinely swarm-wide
matrix settings stay where they are.

mkRenamedOptionModule keeps existing configs evaluating with one
warning naming both paths.

The sweep for readers had to be unanchored and cross-language: three
of them were outside nix, including a hive-c0re error message telling
the operator to set the old name. A dotted grep also cannot see the
rename module's own list form, so that was checked separately.
2026-08-30 15:17:02 +02:00
8 changed files with 59 additions and 55 deletions

View file

@ -58,7 +58,7 @@ hivectl forge reconcile-config iris --verbose # include the full diff, not
Manual entry to the same idempotent matrix provisioning flow Manual entry to the same idempotent matrix provisioning flow
`hive-c0re` runs at boot. Requires the `hive-matrix` container to be `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 ```bash
hivectl matrix create-user iris # provision (or re-provision) matrix account for agent `iris` hivectl matrix create-user iris # provision (or re-provision) matrix account for agent `iris`

View file

@ -1,7 +1,7 @@
//! Optional matrix-tuwunel wiring: shared registration token (host) + //! Optional matrix-tuwunel wiring: shared registration token (host) +
//! per-agent UIAA registration → `<agent-state>/matrix-token`. No-op //! per-agent UIAA registration → `<agent-state>/matrix-token`. No-op
//! when the `hive-matrix` container isn't running, so operators who //! 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. //! nothing.
//! //!
//! See `docs/matrix.md::Provisioning flow (registration token)` for //! See `docs/matrix.md::Provisioning flow (registration token)` for

View file

@ -487,7 +487,7 @@ fn require_matrix_present() -> Result<()> {
return Ok(()); return Ok(());
} }
anyhow::bail!( 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 \ here, or services.hyperhive.swarm.matrix.apiUrl to point at an existing one, before \
provisioning matrix users" provisioning matrix users"
) )

View file

@ -54,7 +54,7 @@ let
boot.loader.grub.enable = false; boot.loader.grub.enable = false;
system.stateVersion = "25.11"; system.stateVersion = "25.11";
services.hyperhive.enable = lib.mkForce false; services.hyperhive.enable = lib.mkForce false;
services.hyperhive.swarm.matrix.enable = lib.mkForce false; services.hyperhive.deploy.matrix.enable = lib.mkForce false;
} }
) )
]; ];

View file

@ -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 { nats.enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;

View file

@ -159,28 +159,26 @@ in
# a reading no correctly-built hive should ever have to make. # a reading no correctly-built hive should ever have to make.
HIVE_RESERVED_NAMES = lib.concatStringsSep " " (import ../../reserved-names.nix); HIVE_RESERVED_NAMES = lib.concatStringsSep " " (import ../../reserved-names.nix);
} }
// // lib.optionalAttrs (config.services.hyperhive.swarm.matrix.gatewayHost != null) {
lib.optionalAttrs # Matrix homeserver URL for each agent's hive-matrix-daemon — the
( # gateway vhost (`chat.<swarm-domain>`). Forwarded to agents by meta.rs
config.services.hyperhive.swarm.matrix.enable # alongside HIVE_FORGE_URL; shares the same env-forwarding ordering
&& config.services.hyperhive.swarm.matrix.gatewayHost != null # caveat (value baked at config-generation time).
) #
{ # Deliberately NOT conditioned on this host running the homeserver. A
# In-cluster matrix homeserver URL for each agent's # swarm has one matrix, and every hive's agents talk to it — the hive
# hive-matrix-daemon — the gateway vhost (`matrix.<domain>`). # that hosts it is not the only hive whose agents need its address.
# Forwarded to agents by meta.rs alongside HIVE_FORGE_URL; shares the # `gatewayHost` is swarm-scoped and names that one homeserver from any
# same env-forwarding ordering caveat (value baked at # member hive, so its being set is the whole question.
# config-generation time). #
# # Null forwards nothing rather than falling back to loopback. That
# A domain-less config forwards nothing rather than falling back to # fallback reads as harmless because hive-c0re shares the host netns —
# loopback. The old fallback read as harmless because hive-c0re shares # but the value is handed to *agents*, which do not, so `127.0.0.1`
# the host netns — but the value it produced was handed to *agents*, # there names the agent itself. An absent forward leaves
# which do not, so `127.0.0.1` there names the agent itself. An absent # `hyperhive.matrix.url` null and the daemon no-ops; that is the honest
# forward leaves `hyperhive.matrix.url` null and the daemon no-ops; # answer when there is no matrix vhost to point at.
# that is the honest answer when the hive has no matrix vhost to point HIVE_MATRIX_URL = "http://${config.services.hyperhive.swarm.matrix.gatewayHost}";
# at. }
HIVE_MATRIX_URL = "http://${config.services.hyperhive.swarm.matrix.gatewayHost}";
}
// lib.optionalAttrs (config.services.hyperhive.swarm.matrix.apiUrl != null) { // lib.optionalAttrs (config.services.hyperhive.swarm.matrix.apiUrl != null) {
# Client-server API base hive-c0re uses to provision matrix (register # Client-server API base hive-c0re uses to provision matrix (register
# agent users, create the hive space + chat room, invite members). # agent users, create the hive space + chat room, invite members).

View file

@ -164,6 +164,13 @@ in
[ "services" "hyperhive" "matrix" ] [ "services" "hyperhive" "matrix" ]
[ "services" "hyperhive" "swarm" "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" ] '' (lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "sso" "enable" ] ''
SSO is no longer optional: a homeserver that runs at all delegates SSO is no longer optional: a homeserver that runs at all delegates
login to the swarm's authelia. login to the swarm's authelia.
@ -177,21 +184,6 @@ in
]; ];
options.services.hyperhive.swarm.matrix = { 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 { package = lib.mkOption {
type = lib.types.package; type = lib.types.package;
default = pkgs.matrix-tuwunel; default = pkgs.matrix-tuwunel;
@ -254,9 +246,9 @@ in
apiUrl = lib.mkOption { apiUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str; 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 '' 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}" then "http://127.0.0.1:''${toString services.hyperhive.swarm.matrix.httpPort}"
else null else null
''; '';
@ -411,8 +403,8 @@ in
gui = { gui = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = cfg.enable; default = deployCfg.matrix.enable;
defaultText = lib.literalExpression "config.services.hyperhive.swarm.matrix.enable"; defaultText = lib.literalExpression "config.services.hyperhive.deploy.matrix.enable";
description = '' description = ''
Serve a matrix web client at `matrix.''${services.hyperhive.domain}/`. Serve a matrix web client at `matrix.''${services.hyperhive.domain}/`.
Requires `matrix.gatewayHost != null` (default `matrix.<hive>` Requires `matrix.gatewayHost != null` (default `matrix.<hive>`
@ -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 # Matrix's own gateway surface: the sub-domain vhost, the name the
# hive resolver answers for, and the Accept-header map that vhost's # hive resolver answers for, and the Accept-header map that vhost's
# SPA fallback reads. All three are matrix knowledge and none of # SPA fallback reads. All three are matrix knowledge and none of

View file

@ -48,15 +48,11 @@ in
# Same precedence reasoning as ./local-defaults.nix: fills in for an # Same precedence reasoning as ./local-defaults.nix: fills in for an
# operator who hasn't spoken, yields to one who has. # operator who hasn't spoken, yields to one who has.
config.services.hyperhive.swarm = { #
# The last one still spelled `swarm.*.enable`. Everything else that # Everything derives under `deploy.*` now, because "does THIS host run
# used to derive here — the queue, the SSO provider, the collector, # it" is a per-host decision and `swarm.*` has to be identical on every
# the metrics pair, the log store — now derives below under # host. Same switch, same rule, one attribute path.
# `deploy.*`, because "does THIS host run it" is a per-host decision config.services.hyperhive.deploy.matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices;
# and `swarm.*` has to be identical on every host. Same switch, same
# rule, different attribute path.
matrix.enable = lib.mkDefault swarmCfg.enableRequiredServices;
};
# The collector that feeds the pair above (note: no `swarm.` prefix, # The collector that feeds the pair above (note: no `swarm.` prefix,
# this is ./otel.nix's existing per-hive option). # this is ./otel.nix's existing per-hive option).