matrix: drop c0re /matrix mount, use targetFlags --base-href, surface availability via env (mara on #634)

This commit is contained in:
damocles 2026-05-30 14:56:52 +02:00
commit effe00889f
3 changed files with 44 additions and 51 deletions

View file

@ -51,17 +51,6 @@ pub async fn serve(port: u16, coord: Arc<Coordinator>) -> Result<()> {
);
}
tracing::info!(static_dir = %static_dir.display(), "dashboard static dir resolved");
// Optional matrix-GUI static dist (#607). When `HIVE_MATRIX_GUI_DIR`
// is set and the dir exists, mount it at `/matrix/` as a sibling
// ServeDir before the SPA fallback. Pre-#15 (nginx front) this
// is the simplest way to put fluffychat-web on the same origin as
// the dashboard so the operator has matrix chat one tab away.
let matrix_gui_dir: Option<PathBuf> = std::env::var_os("HIVE_MATRIX_GUI_DIR")
.map(PathBuf::from)
.filter(|p| p.is_dir());
if let Some(dir) = &matrix_gui_dir {
tracing::info!(matrix_gui_dir = %dir.display(), "matrix GUI mount enabled at /matrix");
}
let app = Router::new()
.route("/api/state", get(api_state))
.route("/approve/{id}", post(post_approve))
@ -103,14 +92,6 @@ pub async fn serve(port: u16, coord: Arc<Coordinator>) -> Result<()> {
// /static/dashboard.css → dist/static/dashboard.css, etc.).
.fallback_service(ServeDir::new(&static_dir))
.with_state(AppState { coord });
// Sibling static mount for the optional matrix GUI dist. Layered
// before the SPA fallback so `/matrix/...` resolves there instead
// of falling through to the dashboard.
let app = if let Some(dir) = matrix_gui_dir {
app.nest_service("/matrix", ServeDir::new(dir))
} else {
app
};
let addr = SocketAddr::from(([0, 0, 0, 0], port));
let listener = bind_with_retry(addr).await?;
tracing::info!(%port, "dashboard listening");
@ -242,10 +223,13 @@ struct StateSnapshot {
/// links each container's config + each approval's commit into the
/// forge's `agent-configs` repos.
forge_present: bool,
/// Whether the matrix GUI static dist is mounted at `/matrix/`
/// (`HIVE_MATRIX_GUI_DIR` set + dir exists). Drives the dashboard's
/// `M4TR1X →` tab-strip entry so it doesn't flash a dead link when
/// the operator hasn't opted in (#607).
/// Whether the matrix GUI is reachable at `/matrix/`. Sourced from
/// `HIVE_MATRIX_GUI_ENABLED` env var (set by the c0re NixOS module
/// when `services.hyperhive.matrix.gui.enable` is on). The gateway
/// (hive-gateway.nix) does the actual `/matrix/` static serving;
/// this flag is just an availability signal for iris's dashboard
/// chrome so the `M4TR1X →` tab doesn't flash when the GUI is off
/// (#607, #634).
matrix_gui_enabled: bool,
}
@ -439,9 +423,13 @@ async fn api_state(headers: HeaderMap, State(state): State<AppState>) -> axum::J
port_conflicts,
rebuild_queue: state.coord.rebuild_queue.snapshot(),
forge_present: crate::forge::is_present().await,
matrix_gui_enabled: std::env::var_os("HIVE_MATRIX_GUI_DIR")
.map(PathBuf::from)
.is_some_and(|p| p.is_dir()),
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")
}),
})
}

View file

@ -241,6 +241,15 @@ in
# Agents poll this URL for Forgejo notifications. Derived from
# services.hyperhive.forge.{domain,httpPort} so it tracks forge config changes.
HIVE_FORGE_URL = "http://${config.services.hyperhive.forge.domain}:${toString config.services.hyperhive.forge.httpPort}";
}
// lib.optionalAttrs config.services.hyperhive.matrix.gui.enable {
# Availability flag for `/api/state.matrix_gui_enabled`. The
# gateway (hive-gateway.nix) does the actual static serving of
# fluffychat-web at `/matrix/`; c0re doesn't host the dist
# itself (#634, mara on PR #620). This env var just tells the
# dashboard chrome whether the GUI is reachable so iris's
# `M4TR1X →` tab doesn't show when the GUI is off.
HIVE_MATRIX_GUI_ENABLED = "1";
};
# Matrix GUI static serving lives entirely on the hive-gateway
# nginx since #609 — when gateway is off the operator opts out

View file

@ -183,34 +183,30 @@ in
type = lib.types.package;
default = pkgs.fluffychat-web.overrideAttrs (old: {
# fluffychat-web ships with `<base href="/">` baked into its
# index.html — that's the placeholder flutter would replace
# via `--base-href` at build time. Since hyperhive serves the
# dist at `/matrix/` (not the document root), the literal
# `<base href="/">` would resolve every relative asset path
# (`Imaging.js`, `flutter.js`, `splash/*`, etc.) against the
# ROOT of the origin, leading to 404s on every load (#634).
# Patch the placeholder to `<base href="/matrix/">` at install
# time so the SPA boots correctly under the sub-path mount.
# If/when we move to subdomain routing (#609
# `matrix.${hyperhiveDomain}`), drop this override and revert
# to upstream `pkgs.fluffychat-web` — it'll be at the root
# again.
postInstall = (old.postInstall or "") + ''
${pkgs.gnused}/bin/sed -i \
's|<base href="/">|<base href="/matrix/">|' \
$out/index.html
'';
# index.html — flutter's `--base-href` build flag replaces
# that placeholder. Default upstream build is `--base-href "/"`
# which is wrong for hyperhive's `/matrix/` sub-path mount:
# the browser resolves relative asset paths (`Imaging.js`,
# `flutter.js`, `splash/*`) against the document ROOT,
# producing 404s for every asset (#634). Inject the right
# base-href into the build via nixpkgs's `buildFlutterApplication`
# targetFlags. When subdomain routing lands (#609 —
# `matrix.${hyperhiveDomain}`), drop this override; upstream's
# `/` base-href is correct at the root of a dedicated subdomain.
targetFlags = (old.targetFlags or [ ]) ++ [
"--base-href"
"/matrix/"
];
});
defaultText = lib.literalExpression "pkgs.fluffychat-web (patched for /matrix/ base href)";
defaultText = lib.literalExpression "pkgs.fluffychat-web with --base-href /matrix/";
description = ''
Static web client dist to serve at `/matrix/`. Defaults to
`pkgs.fluffychat-web` (with the `<base href>` patched to
`/matrix/` so relative asset paths resolve under the
sub-path mount, #634). Override to swap for `hydrogen-web`
(lightest), `cinny` (no threads), `element-web` (heaviest,
full features), or an out-of-tree client dist any
replacement also needs its `<base href>` aligned with the
mount path.
`pkgs.fluffychat-web` rebuilt with `--base-href "/matrix/"`
so relative asset paths resolve under the sub-path mount
(#634). Override to swap for `hydrogen-web` (lightest),
`cinny` (no threads), `element-web` (heaviest, full
features), or an out-of-tree client dist any replacement
also needs its `<base href>` aligned with the mount path.
'';
};
};