Watch
0
0
Fork
You've already forked hyperhive
0

gateway: service modules declare their vhost under gateway.vhosts

Ten service modules (forge, matrix chat, authelia, grafana, otel, nats,
swarm-ui, victorialogs, victoriametrics, bao UI) wrote
services.nginx.virtualHosts themselves, each applying the gateway's
listen set, per-name TLS attrs and security headers by hand. They now
declare services.hyperhive.gateway.vhosts.<name> with only their own
locations and options; ./declared-vhosts.nix renders it into the nginx
vhost with listen, TLS and headers added.

An eval assertion refuses a declared vhost that sets listen, addSSL,
onlySSL, enableACME, useACMEHost, sslCertificate or sslCertificateKey,
and one declared while the gateway is off. nats' own leaf is the new
`certificate` field. The rendered nginx vhosts are unchanged.
This commit is contained in:
atlas 2026-10-16 10:20:13 +02:00 • committed by mara
commit ddb583cc22
17 changed files with 652 additions and 513 deletions

View file

@ -465,65 +465,56 @@ in
# nothing else on this name: the monitoring endpoint (`/varz`, `/connz`)
# is never proxied, and every other path is 403.
#
# ⚠️ Not `gateway.lib.tlsFor`, and the name is not in
# `swarm.serviceDomains`. In self-signed mode this vhost serves the
# queue's own leaf (issued for exactly this name, `server_flag` set), so
# a host whose only swarm service is the queue never fronts a services
# name and its gateway does not wait for the swarm-services leaf.
# ⚠️ In self-signed mode this vhost serves the queue's own leaf
# (`certificate`; issued for exactly this name, `server_flag` set), not
# the gateway's pick for the name, and the name is not in
# `swarm.serviceDomains`.
#
# `forceSSL` for the reason ./swarm-victorialogs.nix gives: authelia
# answers a plain-http auth subrequest with 400.
services.nginx.virtualHosts."${cfg.domain}" =
(
if gatewayServesQueueLeaf then
{
sslCertificate = "${gatewayTlsDir}/cert.pem";
sslCertificateKey = "${gatewayTlsDir}/key.pem";
}
else
builtins.removeAttrs (gatewayCfg.lib.tlsFor cfg.domain) [ "addSSL" ]
)
// {
forceSSL = true;
listen = gatewayCfg.lib.listen;
extraConfig = gatewayCfg.lib.securityHeaders;
locations = {
"/".return = "403";
services.hyperhive.gateway.vhosts."${cfg.domain}" = {
certificate = lib.mkIf gatewayServesQueueLeaf {
cert = "${gatewayTlsDir}/cert.pem";
key = "${gatewayTlsDir}/key.pem";
};
forceSSL = true;
locations = {
"/".return = "403";
# The collector requests exactly this URL, declared as
# `publishedScrapeTargets.nats` in ./swarm-otel-service.nix; the
# two must agree, since that string is also the token's audience.
# Authelia's rules for it admit the collector's client and deny
# every other subject (`metricsRules` in ./swarm-authelia.nix).
"= /metrics" = {
proxyPass = "http://127.0.0.1:${toString cfg.metricsPort}/metrics";
extraConfig = ''
auth_request /__nats_metrics_authz;
'';
};
# The collector requests exactly this URL, declared as
# `publishedScrapeTargets.nats` in ./swarm-otel-service.nix; the
# two must agree, since that string is also the token's audience.
# Authelia's rules for it admit the collector's client and deny
# every other subject (`metricsRules` in ./swarm-authelia.nix).
"= /metrics" = {
proxyPass = "http://127.0.0.1:${toString cfg.metricsPort}/metrics";
extraConfig = ''
auth_request /__nats_metrics_authz;
'';
};
# The subrequest, same shape as the forge's `= /__forge_metrics_authz`
# (./hive-forge/default.nix): no `error_page 401 =302`, so a scraper
# gets the 401 rather than a login page parsed as metrics.
"= /__nats_metrics_authz" = {
proxyPass = "https://${autheliaCfg.domain}/api/authz/auth-request";
# nixpkgs appends its OWN `Host $host` after extraConfig, which
# would override verifiedProxyTo's — see hive-gateway/vhost-lib.nix.
recommendedProxySettings = false;
extraConfig = ''
internal;
${gatewayCfg.lib.verifiedProxyTo autheliaCfg.domain}
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
};
# The subrequest, same shape as the forge's `= /__forge_metrics_authz`
# (./hive-forge/default.nix): no `error_page 401 =302`, so a scraper
# gets the 401 rather than a login page parsed as metrics.
"= /__nats_metrics_authz" = {
proxyPass = "https://${autheliaCfg.domain}/api/authz/auth-request";
# nixpkgs appends its OWN `Host $host` after extraConfig, which
# would override verifiedProxyTo's — see hive-gateway/vhost-lib.nix.
recommendedProxySettings = false;
extraConfig = ''
internal;
${gatewayCfg.lib.verifiedProxyTo autheliaCfg.domain}
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
};
};
};
# Puts a pair at the paths the vhost above names, before nginx starts:
# nginx refuses a config naming a missing cert file, and that takes the