nix/hive-{matrix,gateway}: host fluffychat at matrix.<hive>/, 301 from <hive>/matrix/ (#772)
mara on #764:9897: "host the fluffy chat app at / as follow up?" Moves fluffychat-web from the bare-domain sub-path (`<hive>/matrix/`) to the matrix sub-domain root (`matrix.<hive>/`). Follow-up to #764 (matrix vhost itself), per mara's gateway-architecture verdict (sub-domain for external standard apps, sub-path for hyperhive-internal). Stacked on `atlas/747-matrix-behind-gateway` — depends on #764 landing first. ## Mechanics **hive-matrix.nix:** - Drop `flutterBuildFlags = [ "--base-href" "/matrix/" ]` from `fluffychat-web-fixed`. Upstream default `--base-href "/"` is correct at sub-domain root. - Update option docs to reflect new mount point. **hive-gateway.nix:** - `$matrix_spa_target` map target flips from `/matrix/index.html` → `/index.html` (sub-domain root now). - New `<hive>/matrix/*` location: `rewrite ^/matrix/(.*)$ matrix.<hive>/$1 permanent;` — 301 redirect preserves bookmark + deep-link compatibility for `<hive>/matrix/#/rooms/...` URLs during the transition. - `<hive>/matrix/config.json` location removed (moved to `/config.json` on the matrix vhost). - Matrix vhost (#764) gains `/` location: serves fluffychat dist as static files with the Accept-header SPA fallback (`/_matrix/` proxying to tuwunel keeps working via nginx longer-prefix-wins precedence). When `gui.enable = false`, `/` returns 404 cleanly. - Matrix vhost gains `= /config.json` for the FluffyChat boot-config pre-fill (#736). ## Verified ``` vhosts: ["_", "forge.test.local", "matrix.test.local"] bare locations: ["/", "/matrix/", "= /.well-known/matrix/client", "= /.well-known/matrix/server"] matrix vhost locations: ["/", "/_matrix/", "= /config.json"] /matrix/ extraConfig: "rewrite ^/matrix/(.*)$ http://matrix.test.local/$1 permanent;" matrix vhost / alias: /nix/store/...fluffychat-web-2.6.0/ ``` Full container toplevel builds clean. ## Risk Medium. Two breaking changes for operators: 1. **Bookmark migration**: `http://<hive>/matrix/#/rooms/...` 301s to `http://matrix.<hive>/#/rooms/...`. Browser bookmarks + shared links keep working via the redirect; can be cleaned up once it's been in the wild long enough. 2. **fluffychat-web dist hash changes**: dropping the `--base-href "/matrix/"` flag changes the derivation hash, so `gui.package` rebuilds even though the source is the same. Operators on substitute caches will fetch the new dist; building from source takes the same time as before. The `.well-known/matrix/{client,server}` delegation (already advertising `matrix.<hive>` per #764) means matrix clients auto-discover the new location — no client config change needed. ## Sequencing **Depends on #764** — needs the matrix vhost to host the new `/` location. Merge after #764 lands + soaks. If #764 changes shape during review I'll rebase + force-push. Closes #772.
This commit is contained in:
parent
ea1c6e4d05
commit
df549ed2a5
2 changed files with 134 additions and 117 deletions
|
|
@ -231,11 +231,14 @@ in
|
|||
# takes over.
|
||||
#
|
||||
# Only emitted when the matrix GUI is on (saves a no-op
|
||||
# `map` directive otherwise).
|
||||
# `map` directive otherwise). Target now points at the
|
||||
# sub-domain-root `/index.html` (fluffychat moved off
|
||||
# `<hive>/matrix/` sub-path to `matrix.<hive>/` root in
|
||||
# #772; `--base-href` reverts to upstream-default `/`).
|
||||
appendHttpConfig = lib.optionalString (matrixCfg.enable && matrixCfg.gui.enable) ''
|
||||
map $http_accept $matrix_spa_target {
|
||||
default "/__matrix_spa_no_html_fallback";
|
||||
"~*text/html" "/matrix/index.html";
|
||||
"~*text/html" "/index.html";
|
||||
}
|
||||
'';
|
||||
virtualHosts = {
|
||||
|
|
@ -247,67 +250,41 @@ in
|
|||
}
|
||||
];
|
||||
locations =
|
||||
# Matrix GUI: when the operator has flipped both
|
||||
# `services.hyperhive.matrix.enable` and `matrix.gui.enable`
|
||||
# on, nginx serves fluffychat-web (or whatever override)
|
||||
# as a static dist at `/matrix/`.
|
||||
# Bare-domain `<hive>/matrix/*` → 301 redirect to the
|
||||
# matrix sub-domain root (#772). fluffychat-web used to
|
||||
# live at this sub-path; #772 moved it to `matrix.<hive>/`
|
||||
# so it gets full sub-domain origin isolation + sub-spec
|
||||
# matches the matrix-spec deploy shape. The redirect
|
||||
# preserves bookmark + deep-link compatibility for
|
||||
# `<hive>/matrix/#/...` URLs during the transition;
|
||||
# operators can drop the redirect block once it's been
|
||||
# in the wild long enough that no stale bookmarks remain.
|
||||
#
|
||||
# SPA fallback (iris/#643, rewritten in #686 per mara
|
||||
# + damocles on PR #729): the original
|
||||
# `try_files $uri $uri/ /matrix/index.html;` shape
|
||||
# silently masked missing assets — flutter's bootstrap
|
||||
# requesting e.g. `/matrix/native_executor.js` got
|
||||
# `index.html` (Content-Type: text/html, status 200)
|
||||
# when the file was absent from the dist, so the JS
|
||||
# runtime never loaded and `/matrix/` rendered blank
|
||||
# without any visible error.
|
||||
#
|
||||
# The followup #729 narrowed it with an extension
|
||||
# allowlist; this version uses `$matrix_spa_target`
|
||||
# (defined in the `appendHttpConfig` above, keyed on
|
||||
# the `Accept` header) so the decision lives in HTTP
|
||||
# semantics rather than a maintained extension list.
|
||||
# Navigations (Accept: text/html) fall to index.html;
|
||||
# asset fetches (Accept: */*, image/*, etc.) get a
|
||||
# clean 404 via the trailing `=404`.
|
||||
lib.optionalAttrs (matrixCfg.enable && matrixCfg.gui.enable) {
|
||||
"/matrix/" = {
|
||||
alias = "${matrixCfg.gui.package}/";
|
||||
extraConfig = ''
|
||||
try_files $uri $uri/ $matrix_spa_target =404;
|
||||
'';
|
||||
};
|
||||
# FluffyChat fetches `/matrix/config.json` directly on
|
||||
# boot for its own branding + default-homeserver
|
||||
# bootstrap, BEFORE asking the user to pick a server
|
||||
# (#736). The upstream `pkgs.fluffychat-web` dist
|
||||
# ships without one, so the fetch 404s and the user
|
||||
# sees the empty "enter homeserver" prompt. Serve a
|
||||
# minimal config that pre-fills `defaultHomeserver`
|
||||
# with the operator's hive domain — the matrix
|
||||
# client then runs `.well-known/matrix/client` against
|
||||
# that domain (already served by the
|
||||
# `= /.well-known/matrix/client` block below) and
|
||||
# discovers the actual tuwunel endpoint.
|
||||
#
|
||||
# Only the `defaultHomeserver` field is overridden —
|
||||
# everything else (branding, audio defaults, etc.)
|
||||
# falls back to fluffychat's hardcoded defaults so
|
||||
# we don't pin against upstream config-schema drift.
|
||||
# No-op when `services.hyperhive.domain` is unset
|
||||
# (the location block is omitted entirely; the SPA
|
||||
# then falls back to its empty form, same as before
|
||||
# #736).
|
||||
} // lib.optionalAttrs (
|
||||
matrixCfg.enable && matrixCfg.gui.enable && hyperhiveDomain != null
|
||||
) {
|
||||
"= /matrix/config.json" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
return 200 '{"defaultHomeserver":"${hyperhiveDomain}"}';
|
||||
'';
|
||||
};
|
||||
}
|
||||
# Only emitted when both the matrix GUI is on AND
|
||||
# `matrixCfg.gatewayHost` is set (else there's no
|
||||
# canonical sub-domain to redirect to).
|
||||
lib.optionalAttrs (
|
||||
matrixCfg.enable
|
||||
&& matrixCfg.gui.enable
|
||||
&& matrixCfg.gatewayHost != null
|
||||
) (
|
||||
let
|
||||
portSuffix = if cfg.port == 80 then "" else ":${toString cfg.port}";
|
||||
target = "http://${matrixCfg.gatewayHost}${portSuffix}";
|
||||
in
|
||||
{
|
||||
# `rewrite ^/matrix/(.*)$ → matrix.<hive>/$1` —
|
||||
# strips the `/matrix/` prefix on the way out so
|
||||
# `<hive>/matrix/#/rooms/...` lands at the right
|
||||
# SPA route on the sub-domain side. `permanent`
|
||||
# emits 301 + sets the canonical Location header.
|
||||
"/matrix/" = {
|
||||
extraConfig = ''
|
||||
rewrite ^/matrix/(.*)$ ${target}/$1 permanent;
|
||||
'';
|
||||
};
|
||||
}
|
||||
)
|
||||
//
|
||||
# `.well-known/matrix/*` auto-discovery (#660): when
|
||||
# `services.hyperhive.matrix.enable` is on and the
|
||||
|
|
@ -507,22 +484,63 @@ in
|
|||
port = cfg.port;
|
||||
}
|
||||
];
|
||||
locations = {
|
||||
"/_matrix/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString matrixCfg.httpPort}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
client_max_body_size 50M;
|
||||
proxy_read_timeout 1h;
|
||||
proxy_send_timeout 1h;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
'';
|
||||
};
|
||||
"/" = {
|
||||
return = "404";
|
||||
};
|
||||
};
|
||||
locations =
|
||||
{
|
||||
"/_matrix/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString matrixCfg.httpPort}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
client_max_body_size 50M;
|
||||
proxy_read_timeout 1h;
|
||||
proxy_send_timeout 1h;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
'';
|
||||
};
|
||||
}
|
||||
//
|
||||
# Fluffychat-web (or override) served at sub-domain
|
||||
# root (#772 — moved from bare-domain `/matrix/`).
|
||||
# nginx location-precedence: longer prefix wins,
|
||||
# so `/_matrix/` (above) handles the matrix API
|
||||
# and `/` falls through to fluffychat for
|
||||
# everything else.
|
||||
#
|
||||
# SPA fallback uses the same Accept-header `$matrix_spa_target`
|
||||
# map from `appendHttpConfig` above — navigations
|
||||
# fall to `/index.html` (now sub-domain-root path),
|
||||
# asset misses return clean 404.
|
||||
#
|
||||
# `= /config.json` serves the FluffyChat boot-config
|
||||
# pre-fill with the operator's hive-domain so the
|
||||
# client's `.well-known/matrix/client` lookup hits
|
||||
# the right delegation endpoint (#736).
|
||||
lib.optionalAttrs (matrixCfg.gui.enable) (
|
||||
{
|
||||
"/" = {
|
||||
alias = "${matrixCfg.gui.package}/";
|
||||
extraConfig = ''
|
||||
try_files $uri $uri/ $matrix_spa_target =404;
|
||||
'';
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (hyperhiveDomain != null) {
|
||||
"= /config.json" = {
|
||||
extraConfig = ''
|
||||
default_type application/json;
|
||||
return 200 '{"defaultHomeserver":"${hyperhiveDomain}"}';
|
||||
'';
|
||||
};
|
||||
}
|
||||
)
|
||||
//
|
||||
# Fall-through `/` when GUI is off: nothing else
|
||||
# lives at the matrix vhost, return 404 cleanly.
|
||||
lib.optionalAttrs (!matrixCfg.gui.enable) {
|
||||
"/" = {
|
||||
return = "404";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,17 +103,14 @@ let
|
|||
};
|
||||
|
||||
# `pkgs.fluffychat-web` with #685's three missing files patched
|
||||
# in via postInstall, plus the existing `--base-href "/matrix/"`
|
||||
# override (#634) for the sub-path mount.
|
||||
# in via postInstall. No `--base-href` override anymore (#772 moves
|
||||
# fluffychat from the bare-domain `<hive>/matrix/` sub-path to the
|
||||
# `matrix.<hive>/` sub-domain root; upstream's default `--base-href
|
||||
# "/"` is correct at sub-domain root). The previous `/matrix/`
|
||||
# override from #634 + #754 (forge sub-domain pattern) lived here
|
||||
# until the matrix sub-domain vhost in #764 made the sub-path
|
||||
# redundant.
|
||||
fluffychat-web-fixed = pkgs.fluffychat-web.overrideAttrs (old: {
|
||||
# `--base-href "/matrix/"` so relative asset paths resolve
|
||||
# under the sub-path mount (#634). Upstream default is `/`,
|
||||
# wrong for hyperhive's `/matrix/` location.
|
||||
flutterBuildFlags = (old.flutterBuildFlags or [ ]) ++ [
|
||||
"--base-href"
|
||||
"/matrix/"
|
||||
];
|
||||
|
||||
# `dart` from the flutter341 closure (already pulled, no
|
||||
# incremental closure cost) so we can compile the web-worker
|
||||
# entry point that buildFlutterApplication skips.
|
||||
|
|
@ -385,21 +382,22 @@ in
|
|||
defaultText = lib.literalExpression "config.services.hyperhive.matrix.enable";
|
||||
description = ''
|
||||
Serve a matrix web client (default `pkgs.fluffychat-web`) as
|
||||
a static dist at `/matrix/` via the hive-gateway nginx
|
||||
(#607 / #634). Defaults to whatever
|
||||
a static dist at the root of the matrix sub-domain vhost
|
||||
(`matrix.''${services.hyperhive.domain}/`, via the hive-gateway
|
||||
nginx — #607 / #634 / #772). Defaults to whatever
|
||||
`services.hyperhive.matrix.enable` is — turning on the
|
||||
homeserver gives you the web client by default; set to
|
||||
`false` explicitly to opt out of the GUI while keeping
|
||||
the homeserver running for agents. Requires
|
||||
`services.hyperhive.gateway.enable` (default on); when
|
||||
gateway is off no one hosts the GUI and the
|
||||
`M4TR1X →` dashboard tab is hidden.
|
||||
`false` explicitly to opt out of the GUI while keeping the
|
||||
homeserver running for agents. Requires
|
||||
`services.hyperhive.gateway.enable` (default on) +
|
||||
`services.hyperhive.matrix.gatewayHost != null` (default
|
||||
`matrix.<hive>`); when either is off no one hosts the GUI
|
||||
and the `M4TR1X →` dashboard tab is hidden.
|
||||
|
||||
fluffychat-web supports per-login server pick — point it at
|
||||
the in-host tuwunel URL (`http://localhost:8008` by
|
||||
default) the first time. The post-#15 nginx-front re-root
|
||||
(`https://matrix.''${services.hyperhive.domain}`) is tracked
|
||||
separately in #609.
|
||||
The `.well-known/matrix/{client,server}` delegation (served
|
||||
on the bare hive-domain) advertises this sub-domain, so
|
||||
clients opened at `http://<hive>/` auto-discover the
|
||||
fluffychat root automatically.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -407,24 +405,25 @@ in
|
|||
type = lib.types.package;
|
||||
default = fluffychat-web-fixed;
|
||||
defaultText = lib.literalMD ''
|
||||
`pkgs.fluffychat-web` rebuilt with `--base-href /matrix/` (#634)
|
||||
and patched via `postInstall` to add the three files
|
||||
`flutter341.buildFlutterApplication` skips: `native_executor.js`
|
||||
(compiled via `dart compile js` from `web/native_executor.dart`),
|
||||
plus `Imaging.js` + `Imaging.wasm` (built from the
|
||||
`native_imaging` dart package's C source via `pkgs.emscripten`).
|
||||
See the `let` block in `nix/modules/hive-matrix.nix` for the
|
||||
full rationale (#685).
|
||||
`pkgs.fluffychat-web` patched via `postInstall` to add the
|
||||
three files `flutter341.buildFlutterApplication` skips:
|
||||
`native_executor.js` (compiled via `dart compile js` from
|
||||
`web/native_executor.dart`), plus `Imaging.js` +
|
||||
`Imaging.wasm` (built from the `native_imaging` dart
|
||||
package's C source via `pkgs.emscripten`). See the `let`
|
||||
block in `nix/modules/hive-matrix.nix` for the full
|
||||
rationale (#685, #772).
|
||||
'';
|
||||
description = ''
|
||||
Static web client dist to serve at `/matrix/`. Defaults to
|
||||
`pkgs.fluffychat-web` rebuilt with `--base-href "/matrix/"`
|
||||
so relative asset paths resolve under the sub-path mount
|
||||
(#634), plus a `postInstall` patch for #685's three missing
|
||||
files. 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.
|
||||
Static web client dist to serve at the matrix sub-domain
|
||||
root (`matrix.''${services.hyperhive.domain}/`). Defaults
|
||||
to `pkgs.fluffychat-web` with the #685 `postInstall` patch
|
||||
for the three missing files. Override to swap for
|
||||
`hydrogen-web` (lightest), `cinny` (no threads),
|
||||
`element-web` (heaviest, full features), or an out-of-tree
|
||||
client dist — any replacement gets served at the sub-domain
|
||||
root with the upstream-default `<base href "/">`, no
|
||||
sub-path gymnastics needed.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue