matrix: serve the web client unconditionally; link it from the swarm domain
Removes services.hyperhive.deploy.matrix.gui.enable and its swarm.matrix.gui.enable alias; both are mkRemovedOptionModule stubs. A host running the homeserver serves fluffychat at gatewayHost's vhost, and the hive's /matrix/ redirect follows the same condition. The swarm-controller builds the Matrix quick link from swarm.matrix.gatewayHost, replacing hive-matrix.nix's per-host entry. HIVE_MATRIX_PUBLIC_URL is set on every hive with a gatewayHost, so `hivectl open matrix` resolves off the homeserver's host too. Drops HIVE_MATRIX_GUI_ENABLED and the dashboard's matrix_gui_enabled field; nothing in the frontend reads it. Refs #4885
This commit is contained in:
parent
8628e0ecdd
commit
f60f8af33b
10 changed files with 48 additions and 96 deletions
|
|
@ -8,7 +8,7 @@ homeserver, on one host. Two namespaces configure it:
|
|||
- `services.hyperhive.swarm.matrix.*` — what the homeserver **is**, as
|
||||
every hive sees it: `serverName`, `gatewayHost`, ports, `allowEncryption`.
|
||||
- `services.hyperhive.deploy.matrix.*` — what the host running it decides:
|
||||
`enable`, `gui.enable`, `openFirewall`, `trustedServers`,
|
||||
`enable`, `gui.package`, `openFirewall`, `trustedServers`,
|
||||
`maxRequestSize`, `sso.clientSecretFile`.
|
||||
|
||||
Vhost routing lives in [`gateway.md`](../networking/gateway.md).
|
||||
|
|
|
|||
|
|
@ -113,19 +113,19 @@ same whichever host runs each service:
|
|||
| Grafana | `services.hyperhive.swarm.grafana.domain` |
|
||||
| Metrics | `services.hyperhive.swarm.victoriametrics.domain` |
|
||||
| Logs | `services.hyperhive.swarm.victorialogs.domain` |
|
||||
| Matrix | `services.hyperhive.swarm.matrix.gatewayHost` |
|
||||
|
||||
`nix/host-modules/swarm-controller.nix` builds these entries. The
|
||||
Matrix and Forge entries, and `swarm-ui.nix`'s entry for this UI's own API
|
||||
docs, come from those services' own modules, and only when the controller's
|
||||
host runs that service. An operator can add entries directly. An
|
||||
empty list hides the button.
|
||||
`nix/host-modules/swarm-controller.nix` builds these entries. The Forge
|
||||
entry, and `swarm-ui.nix`'s entry for this UI's own API docs, come from
|
||||
those services' own modules, and only when the controller's host runs that
|
||||
service. An operator can add entries directly. An empty list hides the
|
||||
button.
|
||||
|
||||
The **Matrix** entry opens the swarm's matrix web client (fluffychat,
|
||||
`services.hyperhive.deploy.matrix.gui.package`) at the homeserver's
|
||||
gateway host, `chat.<swarm domain>` by default. `hive-matrix.nix` adds it
|
||||
only when `services.hyperhive.deploy.matrix.gui.enable` is on and the
|
||||
homeserver has a gateway host, the same condition under which that vhost
|
||||
serves the client at `/`.
|
||||
gateway host, `chat.<swarm domain>` by default. The homeserver's host
|
||||
always serves the client at `/` on that vhost, so the entry is present
|
||||
whenever the swarm names a gateway host.
|
||||
|
||||
<details><summary>Adding a swarm service name: the two wiring sites</summary>
|
||||
|
||||
|
|
|
|||
|
|
@ -73,12 +73,6 @@ pub(super) struct StateSnapshot {
|
|||
/// links each container's config + each approval's commit into the
|
||||
/// forge's `agent-configs` repos.
|
||||
forge_present: bool,
|
||||
/// Whether `services.hyperhive.deploy.matrix.gui.enable` is on. Sourced
|
||||
/// from the `HIVE_MATRIX_GUI_ENABLED` env var the c0re NixOS module
|
||||
/// sets. The matrix client itself is served on the homeserver's
|
||||
/// gateway vhost; the hive's `/matrix/` path redirects there
|
||||
/// (`nix/host-modules/hive-gateway/vhosts.nix`).
|
||||
matrix_gui_enabled: bool,
|
||||
/// Whether `hive-gateway` is in front of this dashboard. Sourced
|
||||
/// from the `HIVE_GATEWAY_ENABLED` env var, which the c0re NixOS
|
||||
/// module now always sets (the gateway runs unconditionally
|
||||
|
|
@ -313,17 +307,10 @@ pub(super) async fn api_state(
|
|||
tombstones,
|
||||
port_conflicts,
|
||||
forge_present: crate::forge::is_present().await,
|
||||
matrix_gui_enabled: std::env::var_os("HIVE_MATRIX_GUI_ENABLED").is_some_and(|v| {
|
||||
// Accept any truthy string ("1", "true", "yes") since the
|
||||
// env var is set by NixOS module wiring with the literal
|
||||
// "1"; defensive parse so manual overrides also work.
|
||||
let s = v.to_string_lossy().to_ascii_lowercase();
|
||||
matches!(s.as_str(), "1" | "true" | "yes")
|
||||
}),
|
||||
gateway_enabled: std::env::var_os("HIVE_GATEWAY_ENABLED").is_some_and(|v| {
|
||||
// Same truthy-string parse as `matrix_gui_enabled`; the
|
||||
// env var is set by the c0re NixOS module to the literal
|
||||
// "1" — the gateway always runs alongside hyperhive.
|
||||
// Accept any truthy string ("1", "true", "yes"): the c0re
|
||||
// NixOS module sets the literal "1" (the gateway always runs
|
||||
// alongside hyperhive), and manual overrides also parse.
|
||||
let s = v.to_string_lossy().to_ascii_lowercase();
|
||||
matches!(s.as_str(), "1" | "true" | "yes")
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub(crate) async fn open_url(socket: &Path, target: OpenTarget) -> Result<()> {
|
|||
),
|
||||
OpenTarget::Matrix => (
|
||||
urls.matrix,
|
||||
"the matrix GUI URL needs `services.hyperhive.deploy.matrix.gui.enable = true`",
|
||||
"the matrix GUI URL needs `services.hyperhive.swarm.matrix.gatewayHost` set",
|
||||
),
|
||||
};
|
||||
let url = url.with_context(|| format!("no URL available for this surface — {hint}"))?;
|
||||
|
|
|
|||
|
|
@ -277,10 +277,16 @@ in
|
|||
The old token file at /var/lib/hyperhive/matrix-register-token is read by
|
||||
nothing now and can be deleted. See docs/integrations/matrix.md.
|
||||
'')
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "hyperhive" "swarm" "matrix" "gui" "enable" ]
|
||||
[ "services" "hyperhive" "deploy" "matrix" "gui" "enable" ]
|
||||
)
|
||||
(lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "matrix" "gui" "enable" ] ''
|
||||
The matrix web client has no on/off switch: every host that runs the
|
||||
homeserver serves it at services.hyperhive.swarm.matrix.gatewayHost,
|
||||
and the swarm UI links to it. Remove this definition.
|
||||
'')
|
||||
(lib.mkRemovedOptionModule [ "services" "hyperhive" "deploy" "matrix" "gui" "enable" ] ''
|
||||
The matrix web client has no on/off switch: every host that runs the
|
||||
homeserver serves it at services.hyperhive.swarm.matrix.gatewayHost,
|
||||
and the swarm UI links to it. Remove this definition.
|
||||
'')
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "hyperhive" "swarm" "matrix" "sso" "clientSecretFile" ]
|
||||
[ "services" "hyperhive" "deploy" "matrix" "sso" "clientSecretFile" ]
|
||||
|
|
|
|||
|
|
@ -191,12 +191,6 @@ in
|
|||
# one.
|
||||
HIVE_MATRIX_API_URL = config.services.hyperhive.swarm.matrix.apiUrl;
|
||||
}
|
||||
// lib.optionalAttrs config.services.hyperhive.deploy.matrix.gui.enable {
|
||||
# Surfaces as `matrix_gui_enabled` in the dashboard's `/api/state`.
|
||||
# The matrix GUI is served entirely by the gateway nginx. Gateway
|
||||
# routing detail: docs/networking/gateway.md::Vhost map.
|
||||
HIVE_MATRIX_GUI_ENABLED = "1";
|
||||
}
|
||||
// {
|
||||
# The gateway always runs, so the dashboard always builds
|
||||
# same-origin `/agent/<name>/` links (never the direct
|
||||
|
|
@ -216,17 +210,11 @@ in
|
|||
# forge links rather than emitting one it can't justify.
|
||||
HIVE_FORGE_PUBLIC_URL = config.services.hyperhive.swarm.forge.publicUrl;
|
||||
}
|
||||
//
|
||||
lib.optionalAttrs
|
||||
(
|
||||
config.services.hyperhive.deploy.matrix.gui.enable
|
||||
&& config.services.hyperhive.swarm.matrix.gatewayHost != null
|
||||
)
|
||||
{
|
||||
// lib.optionalAttrs (config.services.hyperhive.swarm.matrix.gatewayHost != null) {
|
||||
# Browser-facing matrix GUI (fluffychat) URL — the gateway
|
||||
# vhost (`gatewayHost`, `chat.<swarm-domain>` by default). Surfaced via the daemon's `Urls`
|
||||
# request for `hivectl open matrix`. Absent when the GUI is off
|
||||
# or no gatewayHost is set (no browser-reachable matrix vhost).
|
||||
# request for `hivectl open matrix`. Absent when no gatewayHost is
|
||||
# set (no browser-reachable matrix vhost).
|
||||
HIVE_MATRIX_PUBLIC_URL = "https://${config.services.hyperhive.swarm.matrix.gatewayHost}/";
|
||||
}
|
||||
// lib.optionalAttrs (config.services.hyperhive.swarm.snapshotStore.address != null) {
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ let
|
|||
# by default; legacy deep-link shim during the fluffychat sub-domain move).
|
||||
# See `docs/networking/gateway.md`.
|
||||
matrixRedirectLocations =
|
||||
lib.optionalAttrs
|
||||
(matrixDeployCfg.enable && matrixDeployCfg.gui.enable && matrixCfg.gatewayHost != null)
|
||||
lib.optionalAttrs (matrixDeployCfg.enable && matrixCfg.gatewayHost != null)
|
||||
(
|
||||
let
|
||||
target = "${publicScheme}://${matrixCfg.gatewayHost}${publicPortSuffix}";
|
||||
|
|
|
|||
|
|
@ -537,22 +537,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
gui.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = deployCfg.matrix.enable;
|
||||
defaultText = lib.literalExpression "config.services.hyperhive.deploy.matrix.enable";
|
||||
description = ''
|
||||
Serve a matrix web client at `gatewayHost`'s vhost (`chat.<swarm-domain>`
|
||||
by default) and add the swarm UI's **Matrix** quick link to it
|
||||
(`services.hyperhive.swarm.controller.links`). Requires
|
||||
`gatewayHost != null`; the gateway itself always runs. See
|
||||
`docs/networking/gateway.md` for the discovery flow that lets clients
|
||||
auto-find the sub-domain. The client build itself is
|
||||
`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;
|
||||
|
|
@ -667,19 +651,6 @@ in
|
|||
# through the hive's dnsmasq whether or not the gateway fronts it.
|
||||
services.hyperhive.gateway.dns.enable = lib.mkDefault true;
|
||||
|
||||
# This swarm-ui quick-links entry. Gated on `gui.enable` too, not just
|
||||
# `gatewayHost != null`: `/` on that vhost only serves fluffychat
|
||||
# (below) when the GUI is on — otherwise the link would 404. See
|
||||
# docs/swarm/ui.md::Quick links and
|
||||
# `services.hyperhive.swarm.controller.links`'s description.
|
||||
services.hyperhive.swarm.controller.links =
|
||||
lib.optional (cfg.gatewayHost != null && deployCfg.matrix.gui.enable)
|
||||
{
|
||||
label = "Matrix";
|
||||
icon = "💬";
|
||||
url = "https://${cfg.gatewayHost}/";
|
||||
};
|
||||
|
||||
# Accept-header SPA map, used only by the `/` location below (see
|
||||
# docs/networking/gateway.md "SPA fallback"): text/html → index.html, else a
|
||||
# sentinel so `try_files` falls through to 404. `appendHttpConfig`
|
||||
|
|
@ -687,7 +658,7 @@ in
|
|||
# contributes instead of replacing it.
|
||||
#
|
||||
# The dashboard needs no equivalent — it routes by path.
|
||||
services.nginx.appendHttpConfig = lib.optionalString deployCfg.matrix.gui.enable ''
|
||||
services.nginx.appendHttpConfig = ''
|
||||
map $http_accept $matrix_spa_target {
|
||||
default "/__matrix_spa_no_html_fallback";
|
||||
"~*text/html" "/index.html";
|
||||
|
|
@ -695,8 +666,8 @@ in
|
|||
'';
|
||||
|
||||
# `server_name = gatewayHost`. `/_matrix/*` → tuwunel (CORS `*`, 50M
|
||||
# body cap, 1h long-poll timeout). `/` serves fluffychat, or 404
|
||||
# with the GUI off. nginx's longest-prefix rule puts `/_matrix/`
|
||||
# body cap, 1h long-poll timeout). `/` serves fluffychat. nginx's
|
||||
# longest-prefix rule puts `/_matrix/`
|
||||
# ahead of `/` with no ordering needed.
|
||||
#
|
||||
# ⚠️ The `.well-known/matrix/*` delegation is deliberately NOT here.
|
||||
|
|
@ -727,8 +698,6 @@ in
|
|||
add_header Access-Control-Allow-Origin *;
|
||||
'';
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs deployCfg.matrix.gui.enable {
|
||||
# fluffychat at sub-domain root, SPA-fallback via the
|
||||
# Accept-header `$matrix_spa_target` map above.
|
||||
"/" = {
|
||||
|
|
@ -746,11 +715,6 @@ in
|
|||
return 200 '{"defaultHomeserver":"${hyperhiveDomain}"}';
|
||||
'';
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (!deployCfg.matrix.gui.enable) {
|
||||
"/" = {
|
||||
return = "404";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -51,7 +51,14 @@ let
|
|||
icon = "📜";
|
||||
inherit (swarmCfg.victorialogs) domain;
|
||||
}
|
||||
];
|
||||
]
|
||||
# A null `gatewayHost` means no vhost fronts the homeserver, so there is
|
||||
# no web client to link to.
|
||||
++ lib.optional (swarmCfg.matrix.gatewayHost != null) {
|
||||
label = "Matrix";
|
||||
icon = "💬";
|
||||
url = "https://${swarmCfg.matrix.gatewayHost}/";
|
||||
};
|
||||
|
||||
# Where the secret store is, and whether this host holds the controller's
|
||||
# own leaf for it. ⚠️ The controller's pair, NOT `deploy.bao.clientCertFile`
|
||||
|
|
@ -451,8 +458,9 @@ in
|
|||
or swarm-ui change.
|
||||
|
||||
The Authelia, Grafana, Metrics and Logs entries come from
|
||||
`services.hyperhive.swarm.<service>.domain`, so they are present
|
||||
whichever host runs each service. `hive-matrix.nix`,
|
||||
`services.hyperhive.swarm.<service>.domain`, and the Matrix entry
|
||||
from `services.hyperhive.swarm.matrix.gatewayHost` when it is set,
|
||||
so they are present whichever host runs each service.
|
||||
`hive-forge/default.nix` and `swarm-ui.nix` contribute their own
|
||||
entries, and only where they are enabled on this host.
|
||||
|
||||
|
|
|
|||
|
|
@ -115,9 +115,9 @@ let
|
|||
Grafana = s.grafana.domain;
|
||||
Metrics = s.victoriametrics.domain;
|
||||
Logs = s.victorialogs.domain;
|
||||
Matrix = s.matrix.gatewayHost;
|
||||
# forge: added once hive-forge/default.nix drops its per-host link
|
||||
# matrix: added once its GUI gate is settled
|
||||
# bao: added once its UI gate is settled
|
||||
# bao: its web UI at `swarm.bao.ui.domain` has no link yet
|
||||
};
|
||||
swarmServiceLinksOf =
|
||||
cfg:
|
||||
|
|
|
|||
Loading…
Reference in a new issue