# Glue: matrix's links on the hive domain's vhost. # # ONE PAIRING PER FILE — matrix → hive domain vhost, and nothing else. # # Two pieces, each under its own condition: # - `.well-known/matrix/{client,server}` is served here only when the hive # domain IS the homeserver's server name (a homeserver that pinned # `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). # - `/matrix/*` redirects to the homeserver where the homeserver runs. # # ⚠️ Both conditions repeat the one ./hive-c0re/vhosts.nix declares the hive # domain vhost under. With it looser, this file alone would declare that # vhost, with discovery and no `/` redirect. { lib, config, ... }: let hyperhiveCfg = config.services.hyperhive; gatewayCfg = hyperhiveCfg.gateway; matrixCfg = hyperhiveCfg.swarm.matrix; 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 { config = lib.mkMerge [ (lib.mkIf (onHiveVhost && hyperhiveCfg.deploy.matrix.enable) { # `/matrix/*` → 301 → `gatewayHost`'s vhost/$1 (`chat.` # by default; legacy deep-link shim for the fluffychat sub-domain). # See `docs/networking/gateway.md`. services.hyperhive.gateway.vhosts.${hyperhiveCfg.domain}.locations."/matrix/" = { extraConfig = '' rewrite ^/matrix/(.*)$ ${homeserverUrl}/$1 permanent; ''; }; }) (lib.mkIf (onHiveVhost && hyperhiveCfg.domain == serverName) { services.hyperhive.gateway.vhosts.${hyperhiveCfg.domain}.locations = { # `.well-known/matrix/{client,server}` discovery JSON, pointing # clients and peers at `gatewayHost`: the homeserver has no other # address. CORS `*` per matrix spec. See `docs/networking/gateway.md`. "= /.well-known/matrix/client" = { extraConfig = '' default_type application/json; ${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 # https-implies-443 rule does NOT apply here. So the port must be # explicit even when it's the HTTPS default, unlike the client # base_url above. Without it, peers federate to :8448 # (closed) while the endpoint actually lives on the gateway's 443 # vhost. See docs/networking/gateway.md discovery flow. "= /.well-known/matrix/server" = { extraConfig = '' default_type application/json; return 200 '{"m.server":"${matrixCfg.gatewayHost}:443"}'; ''; }; }; }) ]; }