diff --git a/hive-c0re/src/meta.rs b/hive-c0re/src/meta.rs index fb803936..3ec17332 100644 --- a/hive-c0re/src/meta.rs +++ b/hive-c0re/src/meta.rs @@ -505,6 +505,7 @@ const CANONICAL_INPUTS: &[&str] = &["nixpkgs", "nixpkgs-unstable"]; const FORWARDED_VARS: &[&str] = &[ "HIVE_FORGE_URL", "HIVE_FORGE_PUBLIC_URL", + "HIVE_MATRIX_URL", "HYPERHIVE_PEERS", "HYPERHIVE_HIVE_DOMAIN", "HYPERHIVE_HIVE_NAME", diff --git a/nix/modules/hive-c0re.nix b/nix/modules/hive-c0re.nix index 3fc87ab3..ef3f9e98 100644 --- a/nix/modules/hive-c0re.nix +++ b/nix/modules/hive-c0re.nix @@ -764,6 +764,27 @@ in else "http://127.0.0.1:${toString config.services.hyperhive.forge.httpPort}"; } + // lib.optionalAttrs config.services.hyperhive.matrix.enable { + # In-cluster matrix homeserver URL for each agent's + # hive-matrix-daemon. Same shape + rationale as HIVE_FORGE_URL: + # - Isolated (private netns): reach tuwunel via the gateway vhost + # (`matrix.`) on plain http:80 — host loopback is dead. + # - Shared netns: direct host loopback on the tuwunel port. + # gatewayHost null-guard falls back to loopback so a domain-less + # config doesn't break eval (it just won't work under isolation, + # which needs a gateway anyway). Forwarded to agents by meta.rs + # alongside HIVE_FORGE_URL; shares the same env-forwarding ordering + # caveat (value baked at config-generation time). + HIVE_MATRIX_URL = + if + config.services.hyperhive.network.enable + && config.services.hyperhive.network.isolateContainers + && config.services.hyperhive.matrix.gatewayHost != null + then + "http://${config.services.hyperhive.matrix.gatewayHost}" + else + "http://127.0.0.1:${toString config.services.hyperhive.matrix.httpPort}"; + } // lib.optionalAttrs config.services.hyperhive.matrix.gui.enable { # Availability flags read by the dashboard's `/api/state`. # Matrix GUI lives entirely on the gateway nginx (matrix tab diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index 8d3b91ee..edd43c25 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -17,6 +17,12 @@ let # from `userName` to keep them coupled. userName = config.hyperhive.user.name; homeDir = "/home/${userName}"; + # Single source of truth for the default matrix homeserver URL, shared + # by the `hyperhive.matrix.url` option default and the daemon-unit guard + # that decides whether to set a unit-level HIVE_MATRIX_URL (so the two + # cannot drift). Matches the daemon's own built-in default + # (`paths::DEFAULT_HOMESERVER`). + matrixUrlDefault = "http://localhost:8008"; in { # Shared scaffolding for every hyperhive harness container. @@ -288,7 +294,7 @@ in options.hyperhive.matrix.url = lib.mkOption { type = lib.types.str; - default = "http://localhost:8008"; + default = matrixUrlDefault; example = "https://matrix.darkest.space"; description = '' Matrix homeserver URL the agent's `hive-matrix-daemon` connects @@ -1327,10 +1333,20 @@ in after = [ "network-online.target" ]; wants = [ "network-online.target" ]; environment = { - HIVE_MATRIX_URL = config.hyperhive.matrix.url; HIVE_MATRIX_SOCKET = "/run/hive-matrix/socket"; RUST_LOG = "info"; } + # Homeserver URL: by default the daemon inherits the host-forwarded + # HIVE_MATRIX_URL (set isolation-aware by hive-c0re: `matrix.` + # via the gateway under private-netns isolation, loopback otherwise), + # falling back to the daemon's built-in localhost default if the + # forward is absent. A per-agent `hyperhive.matrix.url` override + # (non-default) is set unit-level so it wins over the forwarded value; + # at the default we deliberately DON'T set it so the forwarded + # isolation-aware value isn't shadowed. + // lib.optionalAttrs (config.hyperhive.matrix.url != matrixUrlDefault) { + HIVE_MATRIX_URL = config.hyperhive.matrix.url; + } # Multi-account: serialize the *extra* accounts to the JSON the # daemon parses (`accounts::configured`). Only set when extras are # declared; the daemon always synthesizes the primary `main`