Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7e4028a16 | ||
|
|
a03aafb004 |
1 changed files with 153 additions and 151 deletions
|
|
@ -565,6 +565,148 @@ in
|
||||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
${lib.optionalString cfg.hsts.enable ''add_header Strict-Transport-Security "${hstsDirectives}" always;''}
|
${lib.optionalString cfg.hsts.enable ''add_header Strict-Transport-Security "${hstsDirectives}" always;''}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# Forge sub-domain vhost. `server_name = forge.domain`, proxies
|
||||||
|
# all `/` → forgejo. Tuned for git: `client_max_body_size 1G`,
|
||||||
|
# `proxy_read_timeout 1h` (multi-GB clones). SSH stays direct on
|
||||||
|
# `forge.sshPort`. See `docs/gateway.md`. Empty attrset when the
|
||||||
|
# forge isn't behind the gateway.
|
||||||
|
forgeVhost = lib.optionalAttrs (forgeCfg.enable or false && forgeCfg.behindGateway or false) {
|
||||||
|
"${forgeCfg.domain}" = vhostTls // {
|
||||||
|
listen = vhostListen;
|
||||||
|
extraConfig = securityHeaders;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://127.0.0.1:${toString forgeCfg.httpPort}/";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = ''
|
||||||
|
proxy_buffering off;
|
||||||
|
client_max_body_size 1G;
|
||||||
|
proxy_read_timeout 1h;
|
||||||
|
proxy_send_timeout 1h;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Matrix sub-domain vhost. `server_name = matrixCfg.gatewayHost`.
|
||||||
|
# `/_matrix/*` → tuwunel (CORS *, 50M body cap, 1h long-poll
|
||||||
|
# timeout). `/` serves fluffychat or 404 if GUI off. nginx
|
||||||
|
# longer-prefix-wins puts `/_matrix/` ahead of `/`. See
|
||||||
|
# `docs/gateway.md`. Empty attrset when matrix has no gateway host.
|
||||||
|
matrixVhost = lib.optionalAttrs (matrixCfg.enable && matrixCfg.gatewayHost != null) {
|
||||||
|
"${matrixCfg.gatewayHost}" = vhostTls // {
|
||||||
|
listen = vhostListen;
|
||||||
|
extraConfig = securityHeaders;
|
||||||
|
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;
|
||||||
|
${securityHeaders}
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (matrixCfg.gui.enable) (
|
||||||
|
{
|
||||||
|
# fluffychat at sub-domain root, SPA-fallback via
|
||||||
|
# the Accept-header `$matrix_spa_target` map.
|
||||||
|
"/" = {
|
||||||
|
alias = "${matrixCfg.gui.package}/";
|
||||||
|
extraConfig = ''
|
||||||
|
try_files $uri $uri/ $matrix_spa_target =404;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (hyperhiveDomain != null) {
|
||||||
|
# FluffyChat boot-config pre-fill so the client's
|
||||||
|
# `.well-known/matrix/client` lookup hits the
|
||||||
|
# right delegation endpoint.
|
||||||
|
"= /config.json" = {
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
return 200 '{"defaultHomeserver":"${hyperhiveDomain}"}';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// lib.optionalAttrs (!matrixCfg.gui.enable) {
|
||||||
|
"/" = {
|
||||||
|
return = "404";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# `_` (default) server location groups, lifted out of the inline
|
||||||
|
# `//`-chain so the two matrix groups (each with its own `let`)
|
||||||
|
# read on their own. Composed into the `_` vhost's `locations`
|
||||||
|
# below alongside the still-inline agent/dashboard/auth groups.
|
||||||
|
|
||||||
|
# `<hive>/matrix/*` → 301 → `matrix.<hive>/$1` (legacy deep-link
|
||||||
|
# shim during the fluffychat sub-domain move). See `docs/gateway.md`.
|
||||||
|
matrixRedirectLocations =
|
||||||
|
lib.optionalAttrs (matrixCfg.enable && matrixCfg.gui.enable && matrixCfg.gatewayHost != null)
|
||||||
|
(
|
||||||
|
let
|
||||||
|
target = "${publicScheme}://${matrixCfg.gatewayHost}${publicPortSuffix}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"/matrix/" = {
|
||||||
|
extraConfig = ''
|
||||||
|
rewrite ^/matrix/(.*)$ ${target}/$1 permanent;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
# `.well-known/matrix/{client,server}` discovery JSON. Points
|
||||||
|
# clients at `matrixCfg.gatewayHost` when set; falls back to direct
|
||||||
|
# `<hive>:<httpPort>`. CORS `*` per matrix spec. The `m.server`
|
||||||
|
# port-8448 carve-out is documented inline. See `docs/gateway.md`.
|
||||||
|
wellKnownLocations = lib.optionalAttrs (matrixCfg.enable && hyperhiveDomain != null) (
|
||||||
|
let
|
||||||
|
clientBaseUrl =
|
||||||
|
if matrixCfg.gatewayHost != null then
|
||||||
|
"${publicScheme}://${matrixCfg.gatewayHost}${publicPortSuffix}"
|
||||||
|
else
|
||||||
|
"${publicScheme}://${hyperhiveDomain}:${toString matrixCfg.httpPort}";
|
||||||
|
# `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; `publicPortSuffix`
|
||||||
|
# (which drops :443) is right for the client base_url above but
|
||||||
|
# wrong for federation delegation. Without this, peers federate to
|
||||||
|
# <gatewayHost>:8448 (closed) while the endpoint actually lives on
|
||||||
|
# the gateway's 443 vhost. See docs/gateway.md discovery flow.
|
||||||
|
serverHostPort =
|
||||||
|
if matrixCfg.gatewayHost != null then
|
||||||
|
"${matrixCfg.gatewayHost}:${toString publicPort}"
|
||||||
|
else
|
||||||
|
"${hyperhiveDomain}:${toString matrixCfg.httpPort}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"= /.well-known/matrix/client" = {
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
${securityHeaders}
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
return 200 '{"m.homeserver":{"base_url":"${clientBaseUrl}"}}';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"= /.well-known/matrix/server" = {
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/json;
|
||||||
|
return 200 '{"m.server":"${serverHostPort}"}';
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
system.stateVersion = "26.05";
|
system.stateVersion = "26.05";
|
||||||
|
|
@ -657,14 +799,13 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
# nginx reload is triggered from the HOST side by hive-c0re
|
# nginx reload is triggered from the HOST side by hive-c0re
|
||||||
# via `systemctl -M hive-gateway reload nginx` — lets systemd
|
# via `systemctl -M hive-gateway reload nginx` after each
|
||||||
# resolve the nginx binary path, avoiding exit-203 EXEC failures.
|
# agents.conf write — letting systemd resolve the nginx binary
|
||||||
# after each agents.conf write. A path unit watching the
|
# path avoids exit-203 EXEC failures. A path unit watching the
|
||||||
# bind-mounted file inside the container was tried first
|
# bind-mounted file inside the container was tried first but
|
||||||
# (A path unit inside the container was tried but IN_MOVED_TO from an atomic rename on the host
|
# doesn't work: an IN_MOVED_TO from an atomic rename on the host
|
||||||
# does not propagate across the nspawn mount-namespace boundary,
|
# does not propagate across the nspawn mount-namespace boundary.
|
||||||
# does not cross the mount-namespace boundary. Host-side trigger is the
|
# The host-side trigger is the correct approach.
|
||||||
# correct approach.
|
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -687,72 +828,8 @@ in
|
||||||
"_" = vhostTls // {
|
"_" = vhostTls // {
|
||||||
listen = vhostListen;
|
listen = vhostListen;
|
||||||
locations =
|
locations =
|
||||||
# `<hive>/matrix/*` → 301 → `matrix.<hive>/$1`
|
matrixRedirectLocations
|
||||||
# (fluffychat moved to sub-domain root; this
|
// wellKnownLocations
|
||||||
# keeps bookmarks + deep-links working during the
|
|
||||||
# transition). See `docs/gateway.md` for the vhost
|
|
||||||
# map.
|
|
||||||
lib.optionalAttrs (matrixCfg.enable && matrixCfg.gui.enable && matrixCfg.gatewayHost != null) (
|
|
||||||
let
|
|
||||||
target = "${publicScheme}://${matrixCfg.gatewayHost}${publicPortSuffix}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
"/matrix/" = {
|
|
||||||
extraConfig = ''
|
|
||||||
rewrite ^/matrix/(.*)$ ${target}/$1 permanent;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
//
|
|
||||||
# `.well-known/matrix/{client,server}` discovery JSON.
|
|
||||||
# Points clients at `matrixCfg.gatewayHost` (sub-domain
|
|
||||||
# vhost) when set; falls back to direct `<hive>:<httpPort>`
|
|
||||||
# when no gateway target. CORS `*` per matrix spec.
|
|
||||||
# See `docs/gateway.md` "Discovery flow" for the full
|
|
||||||
# client-bootstrap sequence.
|
|
||||||
lib.optionalAttrs (matrixCfg.enable && hyperhiveDomain != null) (
|
|
||||||
let
|
|
||||||
clientBaseUrl =
|
|
||||||
if matrixCfg.gatewayHost != null then
|
|
||||||
"${publicScheme}://${matrixCfg.gatewayHost}${publicPortSuffix}"
|
|
||||||
else
|
|
||||||
"${publicScheme}://${hyperhiveDomain}:${toString matrixCfg.httpPort}";
|
|
||||||
# `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; `publicPortSuffix` (which drops
|
|
||||||
# :443) is right for the client base_url above but
|
|
||||||
# wrong for federation delegation. Without this,
|
|
||||||
# peers federate to <gatewayHost>:8448 (closed) while
|
|
||||||
# the endpoint actually lives on the gateway's 443
|
|
||||||
# vhost. See docs/gateway.md discovery flow.
|
|
||||||
serverHostPort =
|
|
||||||
if matrixCfg.gatewayHost != null then
|
|
||||||
"${matrixCfg.gatewayHost}:${toString publicPort}"
|
|
||||||
else
|
|
||||||
"${hyperhiveDomain}:${toString matrixCfg.httpPort}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
"= /.well-known/matrix/client" = {
|
|
||||||
extraConfig = ''
|
|
||||||
default_type application/json;
|
|
||||||
${securityHeaders}
|
|
||||||
add_header Access-Control-Allow-Origin *;
|
|
||||||
return 200 '{"m.homeserver":{"base_url":"${clientBaseUrl}"}}';
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"= /.well-known/matrix/server" = {
|
|
||||||
extraConfig = ''
|
|
||||||
default_type application/json;
|
|
||||||
return 200 '{"m.server":"${serverHostPort}"}';
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
//
|
//
|
||||||
# `/agent/` catch-all: hits when an operator
|
# `/agent/` catch-all: hits when an operator
|
||||||
# requests `/agent/<unknown>/...`. Without this the
|
# requests `/agent/<unknown>/...`. Without this the
|
||||||
|
|
@ -879,83 +956,8 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//
|
// forgeVhost
|
||||||
# Forge sub-domain vhost. `server_name =
|
// matrixVhost;
|
||||||
# forge.domain`, proxies all `/` → forgejo. Tuned for
|
|
||||||
# git: `client_max_body_size 1G`, `proxy_read_timeout 1h`
|
|
||||||
# (multi-GB clones). SSH stays direct on `forge.sshPort`.
|
|
||||||
# See `docs/gateway.md`.
|
|
||||||
lib.optionalAttrs (forgeCfg.enable or false && forgeCfg.behindGateway or false) {
|
|
||||||
"${forgeCfg.domain}" = vhostTls // {
|
|
||||||
listen = vhostListen;
|
|
||||||
extraConfig = securityHeaders;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:${toString forgeCfg.httpPort}/";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_buffering off;
|
|
||||||
client_max_body_size 1G;
|
|
||||||
proxy_read_timeout 1h;
|
|
||||||
proxy_send_timeout 1h;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
//
|
|
||||||
# Matrix sub-domain vhost. `server_name =
|
|
||||||
# matrixCfg.gatewayHost`. `/_matrix/*` → tuwunel (CORS *,
|
|
||||||
# 50M body cap, 1h long-poll timeout). `/` serves
|
|
||||||
# fluffychat or 404 if GUI off. nginx
|
|
||||||
# longer-prefix-wins puts `/_matrix/` ahead of `/`.
|
|
||||||
# See `docs/gateway.md`.
|
|
||||||
lib.optionalAttrs (matrixCfg.enable && matrixCfg.gatewayHost != null) {
|
|
||||||
"${matrixCfg.gatewayHost}" = vhostTls // {
|
|
||||||
listen = vhostListen;
|
|
||||||
extraConfig = securityHeaders;
|
|
||||||
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;
|
|
||||||
${securityHeaders}
|
|
||||||
add_header Access-Control-Allow-Origin *;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (matrixCfg.gui.enable) (
|
|
||||||
{
|
|
||||||
# fluffychat at sub-domain root, SPA-fallback via
|
|
||||||
# the Accept-header `$matrix_spa_target` map.
|
|
||||||
"/" = {
|
|
||||||
alias = "${matrixCfg.gui.package}/";
|
|
||||||
extraConfig = ''
|
|
||||||
try_files $uri $uri/ $matrix_spa_target =404;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// lib.optionalAttrs (hyperhiveDomain != null) {
|
|
||||||
# FluffyChat boot-config pre-fill so the client's
|
|
||||||
# `.well-known/matrix/client` lookup hits the
|
|
||||||
# right delegation endpoint.
|
|
||||||
"= /config.json" = {
|
|
||||||
extraConfig = ''
|
|
||||||
default_type application/json;
|
|
||||||
return 200 '{"defaultHomeserver":"${hyperhiveDomain}"}';
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// lib.optionalAttrs (!matrixCfg.gui.enable) {
|
|
||||||
"/" = {
|
|
||||||
return = "404";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Hive-internal DNS resolver, co-located in the
|
# Hive-internal DNS resolver, co-located in the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue