120 lines
3.1 KiB
Nix
120 lines
3.1 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
registry,
|
|
...
|
|
}:
|
|
let
|
|
|
|
generatedUdpStreams = lib.concatLists (
|
|
lib.mapAttrsToList (
|
|
host: routes:
|
|
lib.concatLists (
|
|
lib.mapAttrsToList (
|
|
entry: route: lib.optionals (route.protocol == "udp") (map (mkUdpStream host entry) route.ports)
|
|
) routes
|
|
)
|
|
) registry.route
|
|
);
|
|
|
|
mkUdpStream =
|
|
host: entry: port:
|
|
let
|
|
address =
|
|
compositeEntry.address
|
|
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
|
compositeEntry = registry.join host entry;
|
|
in
|
|
{
|
|
inherit
|
|
host
|
|
entry
|
|
port
|
|
address
|
|
;
|
|
};
|
|
|
|
generatedStreamConfig = lib.concatMapStringsSep "\n" (stream: ''
|
|
server {
|
|
listen ${toString stream.port} udp;
|
|
proxy_pass ${stream.address}:${toString stream.port};
|
|
}
|
|
'') generatedUdpStreams;
|
|
generatedVirtualHosts = lib.listToAttrs generatedVirtualHostList;
|
|
|
|
# Route registry validation already requires unique domains.
|
|
generatedVirtualHostList = lib.concatLists (
|
|
lib.mapAttrsToList (
|
|
host: routes:
|
|
lib.mapAttrsToList (entry: route: mkVirtualHost host entry route.protocol) (
|
|
lib.filterAttrs (_entry: route: route.protocol != "udp") routes
|
|
)
|
|
) registry.route
|
|
);
|
|
|
|
mkVirtualHost =
|
|
host: entry: mode:
|
|
let
|
|
isHttp = mode == "http";
|
|
address =
|
|
compositeEntry.address
|
|
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
|
|
compositeEntry = registry.join host entry;
|
|
inherit (compositeEntry) route;
|
|
inherit (route) port;
|
|
in
|
|
{
|
|
name = route.domain;
|
|
value = {
|
|
forceSSL = !isHttp;
|
|
enableACME = !isHttp;
|
|
extraConfig = lib.optionalString (route.clientMaxBodySize != null) ''
|
|
client_max_body_size ${route.clientMaxBodySize};
|
|
'';
|
|
locations."/".proxyPass = mkBackend address port;
|
|
};
|
|
};
|
|
|
|
mkBackend = address: port: "http://${address}:${toString port}";
|
|
|
|
mkRegistryPath =
|
|
registryName: host: entry:
|
|
"registry.${registryName}.${host}.${entry}";
|
|
|
|
in
|
|
{
|
|
options.modules.services.reverse-proxy = {
|
|
enable = lib.mkEnableOption "the public edge reverse proxy";
|
|
};
|
|
|
|
config = lib.mkIf config.modules.services.reverse-proxy.enable {
|
|
networking.firewall.allowedTCPPorts = [
|
|
80
|
|
443
|
|
];
|
|
networking.firewall.allowedUDPPorts = map (stream: stream.port) generatedUdpStreams;
|
|
|
|
security.acme = {
|
|
acceptTerms = true;
|
|
defaults.email = "contact@alexion.dev";
|
|
};
|
|
|
|
services.nginx = {
|
|
enable = true;
|
|
commonHttpConfig = ''
|
|
server {
|
|
listen 0.0.0.0:443 ssl default_server;
|
|
listen [::0]:443 ssl default_server;
|
|
ssl_reject_handshake on;
|
|
}
|
|
'';
|
|
recommendedGzipSettings = true;
|
|
recommendedOptimisation = true;
|
|
recommendedProxySettings = true;
|
|
recommendedTlsSettings = true;
|
|
streamConfig = lib.mkIf (generatedUdpStreams != [ ]) generatedStreamConfig;
|
|
virtualHosts = generatedVirtualHosts;
|
|
};
|
|
};
|
|
}
|