serve matrix discovery at the swarm apex, keep the pinned hive case
This commit is contained in:
parent
c9649b258f
commit
2e7d49bb88
10 changed files with 187 additions and 83 deletions
|
|
@ -54,7 +54,9 @@ homeserver.
|
||||||
⚠️ **they're still not interchangeable, and the difference is the
|
⚠️ **they're still not interchangeable, and the difference is the
|
||||||
cost of changing one.** `gatewayHost` is a routing detail clients
|
cost of changing one.** `gatewayHost` is a routing detail clients
|
||||||
rediscover through `.well-known`, so it's safe to move on a running
|
rediscover through `.well-known`, so it's safe to move on a running
|
||||||
deployment. The matrix id format bakes `serverName` into every user and
|
deployment. The controller's host serves that `.well-known` on the swarm
|
||||||
|
domain, and a homeserver pinned to a hive domain gets it on that hive's
|
||||||
|
vhost. The matrix id format bakes `serverName` into every user and
|
||||||
room id, so adopting a new one does **not** rename the existing users and rooms —
|
room id, so adopting a new one does **not** rename the existing users and rooms —
|
||||||
it strands them, because their ids still name a homeserver that no
|
it strands them, because their ids still name a homeserver that no
|
||||||
longer answers.
|
longer answers.
|
||||||
|
|
@ -78,6 +80,10 @@ A rebuild on a host that already has a homeserver prints a
|
||||||
naming the value it's about to default to. It never fails the rebuild, so
|
naming the value it's about to default to. It never fails the rebuild, so
|
||||||
pin the value before the homeserver mints any ids under the default.
|
pin the value before the homeserver mints any ids under the default.
|
||||||
|
|
||||||
|
A pinned hive domain answers `.well-known/matrix/*` itself, built from
|
||||||
|
`gatewayHost`, on any host that runs that hive's gateway. It doesn't need
|
||||||
|
the homeserver on the same host.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## Reach
|
## Reach
|
||||||
|
|
@ -98,7 +104,7 @@ homeserver it crosses the network, so the default is TLS; hive-c0re
|
||||||
verifies the gateway's certificate against the hive trust bundle.
|
verifies the gateway's certificate against the hive trust bundle.
|
||||||
|
|
||||||
Federation peers find the homeserver through `.well-known/matrix/server`
|
Federation peers find the homeserver through `.well-known/matrix/server`
|
||||||
on the hive domain, which names `<gatewayHost>:443`
|
at the server name, which names `<gatewayHost>:443`
|
||||||
([`gateway.md::Discovery flow`](../networking/gateway.md#discovery-flow-matrix)).
|
([`gateway.md::Discovery flow`](../networking/gateway.md#discovery-flow-matrix)).
|
||||||
Port 8448 isn't used.
|
Port 8448 isn't used.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ A service module declares its vhost as `services.hyperhive.gateway.vhosts.<name>
|
||||||
| `<name>.hives.<swarm>/health/` | hive-c0re (`7000`) | always |
|
| `<name>.hives.<swarm>/health/` | hive-c0re (`7000`) | always |
|
||||||
| `<name>.hives.<swarm>/api/docs/` | themed Swagger UI dist (static), behind authelia | always |
|
| `<name>.hives.<swarm>/api/docs/` | themed Swagger UI dist (static), behind authelia | always |
|
||||||
| `<name>.hives.<swarm>/agent/<name>/` | per-agent harness over its unix socket | `agents.conf` (runtime-generated) |
|
| `<name>.hives.<swarm>/agent/<name>/` | per-agent harness over its unix socket | `agents.conf` (runtime-generated) |
|
||||||
| `<hive>/.well-known/matrix/{client,server}` | inline JSON | `deploy.matrix.enable` |
|
| `<swarm>/.well-known/matrix/{client,server}` | inline JSON | `deploy.swarm-controller.enable`, and `swarm.matrix.serverName` is the swarm domain (the default) |
|
||||||
|
| `<hive>/.well-known/matrix/{client,server}` | inline JSON | `swarm.matrix.serverName` is this hive's domain (a pinned homeserver) |
|
||||||
| `<hive>/matrix/` | 301 → `chat.<swarm>/` | `deploy.matrix.enable` and `gatewayHost` set |
|
| `<hive>/matrix/` | 301 → `chat.<swarm>/` | `deploy.matrix.enable` and `gatewayHost` set |
|
||||||
| `<hive>/` (every other path) | 301 → `<name>.hives.<swarm>`, same path | always |
|
| `<hive>/` (every other path) | 301 → `<name>.hives.<swarm>`, same path | always |
|
||||||
|
|
||||||
|
|
@ -208,9 +209,11 @@ When enabled, every vhost adds `Strict-Transport-Security: max-age=…[; include
|
||||||
|
|
||||||
## Discovery flow (matrix)
|
## Discovery flow (matrix)
|
||||||
|
|
||||||
The operator points a client at `<hive>`:
|
The server name's own vhost serves discovery, whichever host runs the homeserver. By default that vhost is the swarm apex on the controller's host; a homeserver pinned to a hive domain gets it on that hive's vhost instead. Both build the JSON from `swarm.matrix.gatewayHost` alone, and the `base_url` carries no port.
|
||||||
|
|
||||||
1. The client fetches `https://<hive>/.well-known/matrix/client` → `{"m.homeserver":{"base_url":"https://chat.<swarm>"}}`.
|
The operator points a client at the server name (`<server-name>` below):
|
||||||
|
|
||||||
|
1. The client fetches `https://<server-name>/.well-known/matrix/client` → `{"m.homeserver":{"base_url":"https://chat.<swarm>"}}`.
|
||||||
2. It connects to `chat.<swarm>/_matrix/client/...`.
|
2. It connects to `chat.<swarm>/_matrix/client/...`.
|
||||||
3. The gateway proxies `/_matrix/*` to tuwunel over its unix socket, `/run/hive-matrix/tuwunel.sock`.
|
3. The gateway proxies `/_matrix/*` to tuwunel over its unix socket, `/run/hive-matrix/tuwunel.sock`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -553,7 +553,7 @@ mechanism.
|
||||||
|
|
||||||
2. **Matrix federation** — when this host runs the homeserver (`deploy.matrix.enable`), tuwunel
|
2. **Matrix federation** — when this host runs the homeserver (`deploy.matrix.enable`), tuwunel
|
||||||
federates with the peer's matrix server (discovered via the peer's
|
federates with the peer's matrix server (discovered via the peer's
|
||||||
`.well-known/matrix/server` delegation, which the gateway serves).
|
`.well-known/matrix/server` delegation, which the controller's host or the pinned hive's gateway serves).
|
||||||
Federation validates the peer's TLS certificate against the matrix
|
Federation validates the peer's TLS certificate against the matrix
|
||||||
**container's** trust bundle, independent of this directory.
|
**container's** trust bundle, independent of this directory.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
# Glue: serve the swarm homeserver's discovery on the hive domain's vhost
|
# Glue: matrix's links on the hive domain's vhost.
|
||||||
# wherever both run.
|
|
||||||
#
|
#
|
||||||
# ONE PAIRING PER FILE — matrix → hive domain vhost, and nothing else.
|
# ONE PAIRING PER FILE — matrix → hive domain vhost, and nothing else.
|
||||||
# Deleting this leaves federation and clients with no `.well-known/matrix/*`
|
|
||||||
# answer at the server name, and the legacy `<hive>/matrix/*` links 404.
|
|
||||||
#
|
#
|
||||||
# The locations sit on the hive domain because the matrix spec reads
|
# Two pieces, each under its own condition:
|
||||||
# delegation off the *server name*: it is the hive answering "where is my
|
# - `.well-known/matrix/{client,server}` is served here only when the hive
|
||||||
# homeserver", not the homeserver answering for itself (./hive-matrix.nix's
|
# domain IS the homeserver's server name (a homeserver that pinned
|
||||||
# vhost on `gatewayHost` carries the rest).
|
# `swarm.matrix.serverName` to it): the spec reads delegation off the
|
||||||
|
# *server name*. The host need not run the homeserver, since the JSON is
|
||||||
|
# built from `swarm.matrix.gatewayHost` alone. For the default server name
|
||||||
|
# (the swarm domain) the swarm UI's apex vhost answers (./swarm-ui.nix).
|
||||||
|
# - `<hive>/matrix/*` redirects to the homeserver where the homeserver runs.
|
||||||
#
|
#
|
||||||
# ⚠️ The condition repeats the one ./hive-c0re/vhosts.nix declares the hive
|
# ⚠️ Both conditions repeat the one ./hive-c0re/vhosts.nix declares the hive
|
||||||
# domain vhost under. With it looser, this file alone would declare that
|
# domain vhost under. With it looser, this file alone would declare that
|
||||||
# vhost, with discovery and no `/` redirect.
|
# vhost, with discovery and no `/` redirect.
|
||||||
{
|
{
|
||||||
|
|
@ -24,53 +25,58 @@ let
|
||||||
matrixCfg = hyperhiveCfg.swarm.matrix;
|
matrixCfg = hyperhiveCfg.swarm.matrix;
|
||||||
|
|
||||||
homeserverUrl = "https://${matrixCfg.gatewayHost}";
|
homeserverUrl = "https://${matrixCfg.gatewayHost}";
|
||||||
|
|
||||||
|
onHiveVhost =
|
||||||
|
matrixCfg.gatewayHost != null
|
||||||
|
&& hyperhiveCfg.deploy.hive-controller.enable
|
||||||
|
&& gatewayCfg.enable
|
||||||
|
&& hyperhiveCfg.swarm.dashboardDomain != null;
|
||||||
|
|
||||||
|
# Same default as `effectiveServerName` in ./hive-matrix.nix.
|
||||||
|
serverName =
|
||||||
|
if matrixCfg.serverName != null then matrixCfg.serverName else hyperhiveCfg.swarm.domain;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config =
|
config = lib.mkMerge [
|
||||||
lib.mkIf
|
(lib.mkIf (onHiveVhost && hyperhiveCfg.deploy.matrix.enable) {
|
||||||
(
|
# `<hive>/matrix/*` → 301 → `gatewayHost`'s vhost/$1 (`chat.<swarm-domain>`
|
||||||
hyperhiveCfg.deploy.matrix.enable
|
# by default; legacy deep-link shim for the fluffychat sub-domain).
|
||||||
&& matrixCfg.gatewayHost != null
|
# See `docs/networking/gateway.md`.
|
||||||
&& hyperhiveCfg.deploy.hive-controller.enable
|
services.hyperhive.gateway.vhosts.${hyperhiveCfg.domain}.locations."/matrix/" = {
|
||||||
&& gatewayCfg.enable
|
extraConfig = ''
|
||||||
&& hyperhiveCfg.swarm.dashboardDomain != null
|
rewrite ^/matrix/(.*)$ ${homeserverUrl}/$1 permanent;
|
||||||
)
|
'';
|
||||||
{
|
};
|
||||||
services.hyperhive.gateway.vhosts.${hyperhiveCfg.domain}.locations = {
|
})
|
||||||
# `<hive>/matrix/*` → 301 → `gatewayHost`'s vhost/$1 (`chat.<swarm-domain>`
|
|
||||||
# by default; legacy deep-link shim for the fluffychat sub-domain).
|
|
||||||
# See `docs/networking/gateway.md`.
|
|
||||||
"/matrix/" = {
|
|
||||||
extraConfig = ''
|
|
||||||
rewrite ^/matrix/(.*)$ ${homeserverUrl}/$1 permanent;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# `.well-known/matrix/{client,server}` discovery JSON, pointing
|
(lib.mkIf (onHiveVhost && hyperhiveCfg.domain == serverName) {
|
||||||
# clients and peers at `gatewayHost`: the homeserver has no other
|
services.hyperhive.gateway.vhosts.${hyperhiveCfg.domain}.locations = {
|
||||||
# address. CORS `*` per matrix spec. See `docs/networking/gateway.md`.
|
# `.well-known/matrix/{client,server}` discovery JSON, pointing
|
||||||
"= /.well-known/matrix/client" = {
|
# clients and peers at `gatewayHost`: the homeserver has no other
|
||||||
extraConfig = ''
|
# address. CORS `*` per matrix spec. See `docs/networking/gateway.md`.
|
||||||
default_type application/json;
|
"= /.well-known/matrix/client" = {
|
||||||
${gatewayCfg.lib.securityHeaders}
|
extraConfig = ''
|
||||||
add_header Access-Control-Allow-Origin *;
|
default_type application/json;
|
||||||
return 200 '{"m.homeserver":{"base_url":"${homeserverUrl}"}}';
|
${gatewayCfg.lib.securityHeaders}
|
||||||
'';
|
add_header Access-Control-Allow-Origin *;
|
||||||
};
|
return 200 '{"m.homeserver":{"base_url":"${homeserverUrl}"}}';
|
||||||
# `m.server` is NOT a URL: per the matrix server-server spec
|
'';
|
||||||
# (Resolving Server Names) a delegated host with NO port resolves
|
};
|
||||||
# to the federation default 8448 (after the SRV check) — the
|
# `m.server` is NOT a URL: per the matrix server-server spec
|
||||||
# https-implies-443 rule does NOT apply here. So the port must be
|
# (Resolving Server Names) a delegated host with NO port resolves
|
||||||
# explicit even when it's the HTTPS default, unlike the client
|
# to the federation default 8448 (after the SRV check) — the
|
||||||
# base_url above. Without it, peers federate to <gatewayHost>:8448
|
# https-implies-443 rule does NOT apply here. So the port must be
|
||||||
# (closed) while the endpoint actually lives on the gateway's 443
|
# explicit even when it's the HTTPS default, unlike the client
|
||||||
# vhost. See docs/networking/gateway.md discovery flow.
|
# base_url above. Without it, peers federate to <gatewayHost>:8448
|
||||||
"= /.well-known/matrix/server" = {
|
# (closed) while the endpoint actually lives on the gateway's 443
|
||||||
extraConfig = ''
|
# vhost. See docs/networking/gateway.md discovery flow.
|
||||||
default_type application/json;
|
"= /.well-known/matrix/server" = {
|
||||||
return 200 '{"m.server":"${matrixCfg.gatewayHost}:443"}';
|
extraConfig = ''
|
||||||
'';
|
default_type application/json;
|
||||||
};
|
return 200 '{"m.server":"${matrixCfg.gatewayHost}:443"}';
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ in
|
||||||
identity to a single hive's domain would make relocating the
|
identity to a single hive's domain would make relocating the
|
||||||
container between hives look like a different homeserver.
|
container between hives look like a different homeserver.
|
||||||
Combined with the `.well-known/matrix/{client,server}` routes
|
Combined with the `.well-known/matrix/{client,server}` routes
|
||||||
the gateway serves at that domain, clients auto-discover the
|
the controller's host serves at that domain, clients auto-discover the
|
||||||
actual matrix endpoint without needing a subdomain. Override
|
actual matrix endpoint without needing a subdomain. Override
|
||||||
here only if you need a different server_name shape (e.g.
|
here only if you need a different server_name shape (e.g.
|
||||||
`chat.example.org` for a bespoke hostname).
|
`chat.example.org` for a bespoke hostname).
|
||||||
|
|
|
||||||
|
|
@ -454,11 +454,10 @@ in
|
||||||
# longest-prefix rule puts `/_matrix/`
|
# longest-prefix rule puts `/_matrix/`
|
||||||
# ahead of `/` with no ordering needed.
|
# ahead of `/` with no ordering needed.
|
||||||
#
|
#
|
||||||
# ⚠️ The `.well-known/matrix/*` delegation is deliberately NOT here.
|
# ⚠️ The `.well-known/matrix/*` delegation is deliberately NOT here:
|
||||||
# It stays on the hive's own vhost because the spec requires it to
|
# the spec requires it at the *server name*. It is served by the swarm
|
||||||
# be served at the *server name*, which is the hive domain — it is
|
# apex (./swarm-ui.nix) for the default server name, or by the hive
|
||||||
# the hive answering "where is my homeserver", not the homeserver
|
# domain's vhost (./glue-matrix-hive-discovery.nix) for a pinned one.
|
||||||
# answering for itself.
|
|
||||||
services.hyperhive.gateway.vhosts = lib.optionalAttrs (cfg.gatewayHost != null) {
|
services.hyperhive.gateway.vhosts = lib.optionalAttrs (cfg.gatewayHost != null) {
|
||||||
"${cfg.gatewayHost}" = {
|
"${cfg.gatewayHost}" = {
|
||||||
locations = {
|
locations = {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,16 @@ let
|
||||||
# rather than a coercion error from here — same idiom as
|
# rather than a coercion error from here — same idiom as
|
||||||
# `swarm-otel-service.nix`'s `domainBase`.
|
# `swarm-otel-service.nix`'s `domainBase`.
|
||||||
apex = if swarmCfg.domain == null then "swarm.invalid" else swarmCfg.domain;
|
apex = if swarmCfg.domain == null then "swarm.invalid" else swarmCfg.domain;
|
||||||
|
|
||||||
|
# Matrix discovery is answered at the server name, so the apex serves it when
|
||||||
|
# that is the swarm domain (the default). A homeserver pinned to a hive
|
||||||
|
# domain is answered by that hive's vhost (./glue-matrix-hive-discovery.nix).
|
||||||
|
# Built from `gatewayHost` alone, so it does not matter which host runs the
|
||||||
|
# homeserver. The URLs carry no port: `gateway.httpsPort` only sets what the
|
||||||
|
# gateway listens on.
|
||||||
|
matrixCfg = swarmCfg.matrix;
|
||||||
|
serverName = if matrixCfg.serverName != null then matrixCfg.serverName else apex;
|
||||||
|
servesMatrixDiscovery = matrixCfg.gatewayHost != null && serverName == apex;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# No `enable` of its own: the UI is on wherever
|
# No `enable` of its own: the UI is on wherever
|
||||||
|
|
@ -196,6 +206,25 @@ in
|
||||||
extraConfig = swarmAuthRequest;
|
extraConfig = swarmAuthRequest;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// lib.optionalAttrs servesMatrixDiscovery {
|
||||||
|
# Same JSON, headers and `:443` as the hive-domain copy in
|
||||||
|
# ./glue-matrix-hive-discovery.nix (see there for why `m.server` names
|
||||||
|
# the port). No `auth_request`: peers and clients fetch these unauthenticated.
|
||||||
|
"= /.well-known/matrix/client" = {
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
${gatewayCfg.lib.securityHeaders}
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
return 200 '{"m.homeserver":{"base_url":"https://${matrixCfg.gatewayHost}"}}';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"= /.well-known/matrix/server" = {
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
return 200 '{"m.server":"${matrixCfg.gatewayHost}:443"}';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
// {
|
// {
|
||||||
# swarm-controller's whole HTTP surface, including the live
|
# swarm-controller's whole HTTP surface, including the live
|
||||||
# `/api/openapi.json` spec — proxied untouched (no URI segment
|
# `/api/openapi.json` spec — proxied untouched (no URI segment
|
||||||
|
|
|
||||||
|
|
@ -662,9 +662,15 @@ let
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "a hive with matrix off serves no matrix discovery endpoint";
|
# The hive domain answers discovery only for a server name pinned to it,
|
||||||
|
# which `bare` does not do. Its vhost exists (the redirect is there), so
|
||||||
|
# the absence arms cannot pass on a misspelled name.
|
||||||
|
name = "an unpinned hive serves no matrix discovery on its domain";
|
||||||
ok =
|
ok =
|
||||||
!(builtins.hasAttr "= /.well-known/matrix/client" bare.services.nginx.virtualHosts."_".locations);
|
let
|
||||||
|
l = bare.services.nginx.virtualHosts."h1.t.local".locations;
|
||||||
|
in
|
||||||
|
l ? "/" && !(l ? "= /.well-known/matrix/client") && !(l ? "= /.well-known/matrix/server");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
# main got eval-borked twice by this exact class of bug (once on the
|
# main got eval-borked twice by this exact class of bug (once on the
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ let
|
||||||
;
|
;
|
||||||
})
|
})
|
||||||
hive
|
hive
|
||||||
|
hiveWithController
|
||||||
runGroup
|
runGroup
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -36,6 +37,16 @@ let
|
||||||
# A hive host that does not run the homeserver: its hive-c0re reaches the
|
# A hive host that does not run the homeserver: its hive-c0re reaches the
|
||||||
# homeserver across the network.
|
# homeserver across the network.
|
||||||
matrixElsewhere = shared.bareWithController;
|
matrixElsewhere = shared.bareWithController;
|
||||||
|
|
||||||
|
# A homeserver whose server name was pinned to the hive domain, on the
|
||||||
|
# controller's host, with no homeserver of its own: the discovery answer
|
||||||
|
# sits on the hive domain and needs neither the homeserver nor the apex.
|
||||||
|
matrixPinned = hiveWithController {
|
||||||
|
swarm.matrix.serverName = "h1.t.local";
|
||||||
|
deploy.swarm-controller.enable = true;
|
||||||
|
deploy.swarm-ui.package = pkgs.emptyDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
cases = [
|
cases = [
|
||||||
{
|
{
|
||||||
# Two limits governed a matrix upload and nothing kept them in agreement,
|
# Two limits governed a matrix upload and nothing kept them in agreement,
|
||||||
|
|
@ -129,32 +140,55 @@ let
|
||||||
== "https://chat.t.local";
|
== "https://chat.t.local";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
# The discovery locations reach the hive domain's vhost from a glue
|
# The legacy redirect reaches the hive domain's vhost from a glue
|
||||||
# module, merged into the vhost hive-c0re declares. The matrix-elsewhere
|
# module, merged into the vhost hive-c0re declares, and only where the
|
||||||
# arm reads the same vhost, which still exists there with its redirect,
|
# homeserver runs. The matrix-elsewhere arm reads the same vhost, which
|
||||||
# so its absence of discovery cannot pass on a misspelled name. The
|
# still exists there with its redirect, so its absence of the redirect
|
||||||
# fixture's gateway is on a non-default TLS port, which none of the URLs
|
# cannot pass on a misspelled name. Under the default server name (the
|
||||||
# carry.
|
# swarm domain) the hive domain answers no discovery on either host.
|
||||||
name = "matrix discovery sits on the hive domain's vhost only where the homeserver runs";
|
# The fixture's gateway is on a non-default TLS port, which none of the
|
||||||
|
# URLs carry.
|
||||||
|
name = "an unpinned hive domain's vhost carries the matrix redirect where the homeserver runs, and no discovery";
|
||||||
ok =
|
ok =
|
||||||
let
|
let
|
||||||
here = matrixNoBaoIdentity.services.nginx.virtualHosts."h1.t.local".locations;
|
here = matrixNoBaoIdentity.services.nginx.virtualHosts."h1.t.local".locations;
|
||||||
elsewhere = matrixElsewhere.services.nginx.virtualHosts."h1.t.local".locations;
|
elsewhere = matrixElsewhere.services.nginx.virtualHosts."h1.t.local".locations;
|
||||||
in
|
in
|
||||||
matrixNoBaoIdentity.services.hyperhive.gateway.httpsPort == 8443
|
matrixNoBaoIdentity.services.hyperhive.gateway.httpsPort == 8443
|
||||||
&& lib.hasInfix ''{"m.homeserver":{"base_url":"https://chat.t.local"}}'' (
|
|
||||||
here."= /.well-known/matrix/client".extraConfig or ""
|
|
||||||
)
|
|
||||||
&& lib.hasInfix ''{"m.server":"chat.t.local:443"}'' (
|
|
||||||
here."= /.well-known/matrix/server".extraConfig or ""
|
|
||||||
)
|
|
||||||
&& lib.hasInfix "rewrite ^/matrix/(.*)$ https://chat.t.local/$1 permanent;" (
|
&& lib.hasInfix "rewrite ^/matrix/(.*)$ https://chat.t.local/$1 permanent;" (
|
||||||
here."/matrix/".extraConfig or ""
|
here."/matrix/".extraConfig or ""
|
||||||
)
|
)
|
||||||
&& lib.hasInfix "return 301 https://h1.hives.t.local$request_uri;" here."/".extraConfig
|
&& lib.hasInfix "return 301 https://h1.hives.t.local$request_uri;" here."/".extraConfig
|
||||||
|
&& !(here ? "= /.well-known/matrix/client")
|
||||||
|
&& !(here ? "= /.well-known/matrix/server")
|
||||||
&& elsewhere ? "/"
|
&& elsewhere ? "/"
|
||||||
&& !(elsewhere ? "= /.well-known/matrix/client")
|
&& !(elsewhere ? "/matrix/")
|
||||||
&& !(elsewhere ? "/matrix/");
|
&& !(elsewhere ? "= /.well-known/matrix/client");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
# A homeserver pinned to the hive domain keeps its discovery on that
|
||||||
|
# vhost, even though the host runs no homeserver, and not on the apex, which is a
|
||||||
|
# different server name. The apex arm is read on a vhost that
|
||||||
|
# exists (its `/` and `/api/` are there), so it cannot pass on a
|
||||||
|
# misspelled name.
|
||||||
|
name = "a server name pinned to the hive domain is answered on the hive domain's vhost and not on the apex";
|
||||||
|
ok =
|
||||||
|
let
|
||||||
|
onHive = matrixPinned.services.nginx.virtualHosts."h1.t.local".locations;
|
||||||
|
apex = matrixPinned.services.nginx.virtualHosts."t.local".locations;
|
||||||
|
in
|
||||||
|
!matrixPinned.services.hyperhive.deploy.matrix.enable
|
||||||
|
&& lib.hasInfix ''{"m.homeserver":{"base_url":"https://chat.t.local"}}'' (
|
||||||
|
onHive."= /.well-known/matrix/client".extraConfig or ""
|
||||||
|
)
|
||||||
|
&& lib.hasInfix ''{"m.server":"chat.t.local:443"}'' (
|
||||||
|
onHive."= /.well-known/matrix/server".extraConfig or ""
|
||||||
|
)
|
||||||
|
&& onHive ? "/"
|
||||||
|
&& apex ? "/"
|
||||||
|
&& apex ? "/api/"
|
||||||
|
&& !(apex ? "= /.well-known/matrix/client")
|
||||||
|
&& !(apex ? "= /.well-known/matrix/server");
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
|
|
|
||||||
|
|
@ -366,6 +366,27 @@ let
|
||||||
name = "a named exposeHostPorts opens its bridge port on the host's own say-so";
|
name = "a named exposeHostPorts opens its bridge port on the host's own say-so";
|
||||||
ok = builtins.elem 5432 (bridgePortsOrNone exposedPortsNoHive);
|
ok = builtins.elem 5432 (bridgePortsOrNone exposedPortsNoHive);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# The default server name is the swarm domain, so the apex answers
|
||||||
|
# discovery from `gatewayHost` alone: this fixture runs no homeserver and
|
||||||
|
# no hive. The URLs carry no port, and `m.server` names 443 because the
|
||||||
|
# spec reads a bare host as 8448. The `/` arm is the presence control on
|
||||||
|
# the vhost; the pinned counterpart is in ./matrix-core.nix.
|
||||||
|
name = "the swarm apex serves both matrix discovery routes under the default server name";
|
||||||
|
ok =
|
||||||
|
let
|
||||||
|
l = swarmUiHere.services.nginx.virtualHosts."t.local".locations;
|
||||||
|
in
|
||||||
|
l ? "/"
|
||||||
|
&& lib.hasInfix ''{"m.homeserver":{"base_url":"https://chat.t.local"}}'' (
|
||||||
|
l."= /.well-known/matrix/client".extraConfig or ""
|
||||||
|
)
|
||||||
|
&& lib.hasInfix ''{"m.server":"chat.t.local:443"}'' (
|
||||||
|
l."= /.well-known/matrix/server".extraConfig or ""
|
||||||
|
)
|
||||||
|
&& !(lib.hasInfix "auth_request" l."= /.well-known/matrix/client".extraConfig)
|
||||||
|
&& !(lib.hasInfix "auth_request" l."= /.well-known/matrix/server".extraConfig);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name = "the old swarm UI package spelling sets the controller's UI package, which the vhost serves";
|
name = "the old swarm UI package spelling sets the controller's UI package, which the vhost serves";
|
||||||
ok =
|
ok =
|
||||||
|
|
@ -547,7 +568,7 @@ let
|
||||||
vh = swarmServicesHere.services.nginx.virtualHosts;
|
vh = swarmServicesHere.services.nginx.virtualHosts;
|
||||||
l = vh."h1.hives.t.local".locations;
|
l = vh."h1.hives.t.local".locations;
|
||||||
in
|
in
|
||||||
l ? "/api/" && l ? "/health/" && vh."h1.t.local".locations ? "= /.well-known/matrix/client"
|
l ? "/api/" && l ? "/health/" && vh."h1.t.local".locations ? "/"
|
||||||
)
|
)
|
||||||
&& !(noHiveLeafAnywhere swarmServicesHere);
|
&& !(noHiveLeafAnywhere swarmServicesHere);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue