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

@ -88,6 +88,8 @@ let
deploy.grafana.plugins = [ ];
deploy.grafana.package = pkgs.emptyDirectory;
swarm.authelia.url = "https://auth.example.invalid";
# Declares a vhost that binds its own `listen`, which the gateway refuses.
gateway.vhosts."own-listen.t.local".listen = [ ];
};
# Did ./host-modules/swarm-grafana.nix refuse this host, and for which of its
@ -479,6 +481,39 @@ let
&& builtins.length selectors == 12
&& lib.all (e: lib.hasInfix "\"service.name\"=\"${stamped.value}\"" e) selectors;
}
{
# A module declares its vhost under `gateway.vhosts` and the gateway adds
# what it owns: the listen set, the cert for the name and the security
# headers ahead of the module's own `extraConfig`.
name = "grafana's vhost is rendered with the gateway's listen set, TLS and security headers";
ok =
let
gw = grafanaOldPath.services.hyperhive.gateway;
v =
grafanaOldPath.services.nginx.virtualHosts.${grafanaOldPath.services.hyperhive.swarm.grafana.domain};
# nginx's `listen` entries come back with defaults filled in
# (`extraParameters`, `proxyProtocol`), so compare the fields set.
listenOf = map (l: {
inherit (l) addr port;
ssl = l.ssl or false;
});
in
listenOf v.listen == listenOf gw.lib.listen
&& lib.hasPrefix gw.lib.securityHeaders v.extraConfig
&& v.addSSL
&& !(v ? certificate);
}
{
# A vhost that sets `listen` itself would bind a port the gateway does
# not consider its own, so the eval refuses it and names the vhost.
name = "a gateway vhost that sets its own listen is refused";
ok = lib.any (
a:
!a.assertion
&& lib.hasInfix "sets attributes the gateway owns" a.message
&& lib.hasInfix "own-listen.t.local.listen" a.message
) grafanaNoIdentity.assertions;
}
];
in
runGroup "grafana" cases