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:
parent
7b50ae57e4
commit
ddb583cc22
17 changed files with 652 additions and 513 deletions
85
nix/host-modules/hive-gateway/declared-vhosts.nix
Normal file
85
nix/host-modules/hive-gateway/declared-vhosts.nix
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Renders `services.hyperhive.gateway.vhosts` into
|
||||
# `services.nginx.virtualHosts`: each declared vhost keeps what its module
|
||||
# wrote and gets the gateway's `listen`, the TLS attributes for its name and
|
||||
# the security headers.
|
||||
#
|
||||
# Its own module rather than part of ./default.nix because the
|
||||
# "declared while the gateway is off" assertion has to hold when
|
||||
# `gateway.enable` is false, where ./default.nix defines nothing.
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
cfg = config.services.hyperhive.gateway;
|
||||
|
||||
# What the gateway owns on a vhost. A declared vhost naming one of these
|
||||
# fails the eval.
|
||||
gatewayOwned = [
|
||||
"listen"
|
||||
"addSSL"
|
||||
"onlySSL"
|
||||
"enableACME"
|
||||
"useACMEHost"
|
||||
"sslCertificate"
|
||||
"sslCertificateKey"
|
||||
];
|
||||
|
||||
offenders = lib.concatMap (
|
||||
name: map (attr: "${name}.${attr}") (lib.filter (a: cfg.vhosts.${name} ? ${a}) gatewayOwned)
|
||||
) (lib.attrNames cfg.vhosts);
|
||||
|
||||
render =
|
||||
name: declared:
|
||||
let
|
||||
own = removeAttrs declared [
|
||||
"_module"
|
||||
"certificate"
|
||||
];
|
||||
base =
|
||||
if declared.certificate != null then
|
||||
{
|
||||
sslCertificate = declared.certificate.cert;
|
||||
sslCertificateKey = declared.certificate.key;
|
||||
}
|
||||
else
|
||||
cfg.lib.tlsFor name;
|
||||
# nixos asserts on a vhost declaring both `addSSL` and `forceSSL`.
|
||||
tls = if own.forceSSL or false then removeAttrs base [ "addSSL" ] else base;
|
||||
in
|
||||
tls
|
||||
// own
|
||||
// {
|
||||
listen = cfg.lib.listen;
|
||||
extraConfig = cfg.lib.securityHeaders + (own.extraConfig or "");
|
||||
};
|
||||
in
|
||||
{
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.enable || cfg.vhosts == { };
|
||||
message = ''
|
||||
services.hyperhive.gateway.vhosts declares ${lib.concatStringsSep ", " (lib.attrNames cfg.vhosts)}
|
||||
while services.hyperhive.gateway.enable is false, so nothing
|
||||
would serve them. Enable the gateway, or drop the service that
|
||||
declares the vhost.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = offenders == [ ];
|
||||
message = ''
|
||||
services.hyperhive.gateway.vhosts sets attributes the gateway owns:
|
||||
${lib.concatStringsSep ", " offenders}
|
||||
|
||||
The gateway sets the listen set and the TLS attributes of every
|
||||
vhost it fronts. Declare only the vhost's own locations and
|
||||
options; to serve a certificate the gateway does not pick, set
|
||||
`certificate` on the vhost.
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
(lib.mkIf cfg.enable {
|
||||
services.nginx.virtualHosts = lib.mapAttrs render cfg.vhosts;
|
||||
})
|
||||
];
|
||||
}
|
||||
Loading…
Reference in a new issue