refactor(3202): the gateway publishes its vhost construction kit

Slice 1 of #3202. The listen set, the per-name TLS attrs and the
security headers move out of vhosts.nix into ./vhost-lib.nix and are
published as `services.hyperhive.gateway.lib` (internal, readOnly).

No behaviour change: vhosts.nix consumes the published value, so the
rendered vhost tree is identical.

The point is the next slice. Today a swarm service's vhost lives in
the gateway because only the gateway knows the port pair, the issuer
for a name, and the header block. Publishing those three is what lets
a service module declare its own vhost without the gateway having to
know that service by name.
This commit is contained in:
atlas 2026-08-13 11:17:41 +02:00 committed by mara
commit d5782965db
4 changed files with 189 additions and 82 deletions

View file

@ -94,6 +94,56 @@ in
'';
};
lib = {
listen = lib.mkOption {
type = lib.types.listOf (lib.types.attrsOf lib.types.raw);
internal = true;
readOnly = true;
description = ''
Read-only: the `listen` set every vhost in front of this
gateway shares (plain http on `port`, TLS on `httpsPort`).
Published so a service module can declare its own vhost
without restating the port pair a vhost that binds a
different set is reachable on a port the gateway does not
consider its own, which is the kind of drift nobody notices
until one name behaves differently from the rest.
'';
};
tlsFor = lib.mkOption {
type = lib.types.functionTo (lib.types.attrsOf lib.types.raw);
internal = true;
readOnly = true;
description = ''
Read-only: `host -> ssl attrs` for a vhost of that name.
Which issuer covers a name is **gateway** knowledge, not the
service's: a swarm service's name can sit outside this hive's
domain, and the hive CA is name-constrained out of it, so that
vhost must serve the swarm-services leaf while everything else
keeps the hive leaf. A service module calls this instead of
deciding deciding is how the vhost and the cert stop
agreeing.
'';
};
securityHeaders = lib.mkOption {
type = lib.types.lines;
internal = true;
readOnly = true;
description = ''
Read-only: the server-scope security headers every vhost in
front of this gateway sets.
nginx does not merge `add_header`: a location that sets one
of its own inherits **none** of these, so such a location must
repeat them. That rule is why this is published rather than
left implicit a service module writing its own `locations`
needs the text, not a description of it.
'';
};
};
useSelfSigned = lib.mkOption {
type = lib.types.bool;
internal = true;