config-perso/kat/proxies/default.nix

238 lines
5.5 KiB
Nix

{
pkgs,
lib,
config,
nodes ? { },
...
}:
let
inherit (lib)
mkOption
mkEnableOption
mkIf
mapAttrs
concatStringsSep
fold
;
inherit (lib.types)
port
listOf
submodule
coercedTo
str
raw
;
redirected-ports-mod.options = {
external = mkOption {
type = port;
};
internal = mkOption {
type = port;
};
};
redirection-port-type = coercedTo port (port: {
external = port;
internal = port;
}) (submodule redirected-ports-mod);
inherit (config.kat) fqdn;
hostname = config.networking.hostName;
cfg = config.kat.proxies;
error-webroot = pkgs.runCommand "${hostname}-error-webroot" { } ''
mkdir $out
cp ${./418.html} $out/418.html
cp ${./599.html} $out/599.html
substituteInPlace $out/* \
--replace-fail 'config.hostname' "${hostname}"
'';
redirections =
fold
(a: b: {
domains = a.domains ++ b.domains;
tcp = a.tcp ++ b.tcp;
udp = a.udp ++ b.udp;
vhosts = a.vhosts // b.vhosts;
})
{
domains = [ ];
tcp = [ ];
udp = [ ];
vhosts = { };
}
(
map (
host:
let
inherit (nodes.${host}.config.kat) fqdn;
host-cfg = nodes.${host}.config.kat.proxies;
in
{
domains = [ fqdn ] ++ host-cfg.aliases;
tcp = map (
{ external, internal }:
{
input = external;
inherit (host-cfg) ip;
out = internal;
}
) host-cfg.open-tcp;
udp = map (
{ external, internal }:
{
input = external;
inherit (host-cfg) ip;
out = internal;
}
) host-cfg.open-udp;
vhosts.${fqdn} = {
inherit (host-cfg) ip aliases;
};
}
) cfg.redirects
);
in
{
options.kat.proxies = {
enable = mkEnableOption "kat-proxies autoconfiguration" // {
default = cfg.redirects != [ ];
defaultText = ''config.kat.proxies.redirects != [ ]'';
};
ip = mkOption {
type = str;
};
aliases = mkOption {
type = listOf str;
default = [ ];
};
open-tcp = mkOption {
type = listOf redirection-port-type;
default = [ ];
};
open-udp = mkOption {
type = listOf redirection-port-type;
default = [ ];
};
redirects = mkOption {
type = listOf str;
default = [ ];
};
test = mkOption {
type = raw;
};
};
config = mkIf cfg.enable {
kat.proxies = {
test = redirections;
aliases = redirections.domains;
open-tcp = map ({ input, ... }: input) redirections.tcp;
open-udp = map ({ input, ... }: input) redirections.udp;
};
networking.firewall = {
allowedTCPPorts = [
80
443
] ++ map ({ internal, ... }: internal) cfg.open-tcp;
allowedUDPPorts = map ({ internal, ... }: internal) cfg.open-udp;
};
security.acme.certs.${fqdn}.extraDomainNames = cfg.aliases;
services.nginx = {
enable = true;
virtualHosts =
mapAttrs (
_:
{ aliases, ip }:
{
useACMEHost = fqdn;
forceSSL = true;
acmeFallbackHost = ip;
acmeFallbackRecommendedProxySettings = true;
serverAliases = aliases;
locations = {
"/.${hostname}/" = {
extraConfig = ''
internal;
error_page 404 =418 /.${hostname}/418.html;
'';
alias = "${error-webroot}/";
};
"/" = {
recommendedProxySettings = true;
proxyPass = "https://${ip}/";
extraConfig = ''
proxy_set_header Connection ''';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
error_page 502 =599 "/.${hostname}/599.html";
'';
};
};
}
) redirections.vhosts
// {
${fqdn} = {
default = true;
enableACME = true;
addSSL = true;
locations = {
"/.${hostname}/" = {
extraConfig = ''
internal;
error_page 404 =418 /.${hostname}/418.html;
'';
alias = "${error-webroot}/";
};
"/" = {
extraConfig = ''
return 418;
error_page 418 =418 /.${hostname}/418.html;
'';
};
};
};
};
streamConfig = concatStringsSep "\n" (
map (
{
input,
ip,
out,
}:
''
server {
listen ${toString input};
listen [::]:${toString input};
proxy_pass ${ip}:${toString out};
}
''
) redirections.tcp
++ map (
{
input,
ip,
out,
}:
''
server {
listen ${toString input} udp;
listen [::]:${toString input} udp;
proxy_pass ${ip}:${toString out};
}
''
) redirections.udp
);
};
};
}