247 lines
6.4 KiB
Nix
247 lines
6.4 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
config,
|
|
...
|
|
}:
|
|
let
|
|
inherit (lib)
|
|
mapAttrsToList
|
|
mkMerge
|
|
splitString
|
|
concatStringsSep
|
|
mkIf
|
|
mkOption
|
|
mkEnableOption
|
|
;
|
|
inherit (lib.types)
|
|
str
|
|
bool
|
|
nullOr
|
|
anything
|
|
attrsOf
|
|
submodule
|
|
listOf
|
|
;
|
|
cfg = config.xyno.services.traefik;
|
|
simpleProxyOpts = mapAttrsToList (
|
|
n: v:
|
|
let
|
|
router = v.routerName;
|
|
service = v.serviceName;
|
|
spl = splitString "." v.host;
|
|
certDomain = if (builtins.length spl) > 2 then concatStringsSep "." (builtins.tail spl) else spl;
|
|
in
|
|
mkMerge [
|
|
(mkIf v.robotProtection {
|
|
routers."${router}-robotstxt" = {
|
|
service = "robotstxt";
|
|
rule = "Host(`${v.host}`) && Path(`/robots.txt`)";
|
|
tls.certResolver = "letsencrypt";
|
|
tls.domains = [
|
|
{
|
|
main = certDomain;
|
|
sans = [ "*.${certDomain}" ];
|
|
}
|
|
];
|
|
};
|
|
services.robotstxt = {
|
|
loadBalancer.servers = [
|
|
{ url = "http://127.0.0.2:8080"; }
|
|
];
|
|
};
|
|
})
|
|
{
|
|
routers.${router} = {
|
|
inherit service;
|
|
inherit (v) middlewares;
|
|
rule = if v.rule != null then v.rule else "Host(`${v.host}`)";
|
|
tls.certResolver = "letsencrypt";
|
|
tls.domains = [
|
|
{
|
|
main = certDomain;
|
|
sans = [ "*.${certDomain}" ];
|
|
}
|
|
];
|
|
};
|
|
services.${service} = {
|
|
loadBalancer.servers = [
|
|
{ url = v.internal; }
|
|
];
|
|
loadBalancer.serversTransport = mkIf (v.transport != null) v.transport;
|
|
};
|
|
}
|
|
]
|
|
) cfg.simpleProxy;
|
|
in
|
|
{
|
|
options.xyno.services.traefik.enable = mkEnableOption "enables traefik";
|
|
options.xyno.services.traefik.noBots = mkOption {
|
|
type = bool;
|
|
default = true;
|
|
};
|
|
options.xyno.services.traefik.simpleProxy = mkOption {
|
|
example = {
|
|
"example" = {
|
|
host = "example.org";
|
|
middlewares = [ "meow" ];
|
|
internal = "http://127.0.0.1:8080";
|
|
};
|
|
};
|
|
default = { };
|
|
type = attrsOf (
|
|
submodule (
|
|
{ config, name,... }:
|
|
{
|
|
options = {
|
|
middlewares = mkOption {
|
|
type = listOf str;
|
|
default = [];
|
|
|
|
};
|
|
internal = mkOption {
|
|
type = str;
|
|
description = "where to proxy to";
|
|
};
|
|
host = mkOption {
|
|
type = str;
|
|
description = "used for the route and tls";
|
|
};
|
|
routerName = mkOption {
|
|
type = str;
|
|
default = "simpleproxy-${name}-router";
|
|
};
|
|
serviceName = mkOption {
|
|
type = str;
|
|
default = "simpleproxy-${name}-service";
|
|
};
|
|
robotProtection = mkOption {
|
|
type = bool;
|
|
default = true;
|
|
description = "robots.txt and (soon) iocane";
|
|
};
|
|
rule = mkOption {
|
|
type = str;
|
|
default = "Host(`${config.host}`)";
|
|
description = "overrides the Host(`\${host}`) rule with something custom if set";
|
|
};
|
|
transport = mkOption {
|
|
type = nullOr anything;
|
|
default = null;
|
|
};
|
|
|
|
};
|
|
}
|
|
)
|
|
);
|
|
|
|
};
|
|
config = mkIf cfg.enable {
|
|
services.nginx = {
|
|
enable = mkIf cfg.noBots true;
|
|
defaultListen = mkIf cfg.noBots [
|
|
{
|
|
addr = "127.0.0.2";
|
|
port = 8080;
|
|
}
|
|
];
|
|
virtualHosts._.default = true;
|
|
virtualHosts._.locations."/".root = pkgs.writeTextFile {
|
|
name = "robots.txt";
|
|
destination = "/robots.txt";
|
|
text = ''
|
|
User-agent: *
|
|
Disallow: /
|
|
'';
|
|
};
|
|
};
|
|
services.traefik = {
|
|
enable = true;
|
|
environmentFiles = [
|
|
config.sops.templates."traefik.env".path
|
|
];
|
|
staticConfigOptions = {
|
|
accessLog = {};
|
|
metrics = mkIf config.xyno.services.monitoring.enable {
|
|
otlp.http.endpoint = "http://localhost:8429/v1/metrics";
|
|
};
|
|
entryponits.web = {
|
|
address = ":80";
|
|
redirections.entryPoint = {
|
|
to = "websecure";
|
|
scheme = "https";
|
|
permanent = true;
|
|
};
|
|
};
|
|
entrypoints.websecure = {
|
|
address = ":443";
|
|
http.tls.certResolver = "letsencrypt";
|
|
http3 = { };
|
|
|
|
};
|
|
log.level = "INFO";
|
|
certificatesResolvers.letsencrypt.acme = {
|
|
email = "ssl@xyno.systems";
|
|
caServer = "https://acme-v02.api.letsencrypt.org/directory";
|
|
dnsChallenge = {
|
|
resolvers = [
|
|
"8.8.8.8"
|
|
"1.1.1.1"
|
|
];
|
|
provider = "desec";
|
|
};
|
|
};
|
|
};
|
|
dynamicConfigOptions = {
|
|
http = mkMerge simpleProxyOpts;
|
|
# tls.options.default = {
|
|
# # mozilla modern
|
|
# minVersion = "VersionTLS13";
|
|
# curvePreferences = [
|
|
# "X25519"
|
|
# "CurveP256"
|
|
# "CurveP384"
|
|
# ];
|
|
# };
|
|
# tls.options.old = {
|
|
# # mozilla intermediate
|
|
# minVersion = "VersionTLS12";
|
|
# curvePreferences = [
|
|
# "X25519"
|
|
# "CurveP256"
|
|
# "CurveP384"
|
|
# ];
|
|
# cipherSuites = [
|
|
# "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
|
# "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
|
|
# "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
|
|
# "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
|
|
# "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"
|
|
# "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
|
|
# ];
|
|
|
|
# };
|
|
};
|
|
};
|
|
networking.firewall.allowedTCPPorts = [
|
|
80
|
|
443
|
|
];
|
|
networking.firewall.allowedUDPPorts = [ 443 ];
|
|
xyno.impermanence.directories = [ config.services.traefik.dataDir ];
|
|
sops.secrets."desec_token" = {
|
|
};
|
|
sops.templates."traefik.env".content = ''
|
|
DESEC_TOKEN=${config.sops.placeholder.desec_token}
|
|
DESEC_PROPAGATION_TIMEOUT=1200
|
|
LEGO_DISABLE_CNAME_SUPPORT=true
|
|
'';
|
|
sops.templates."traefik.env".reloadUnits = [ "traefik.service" ];
|
|
# services.borgmatic.settings.traefikql_databases = [
|
|
# {
|
|
# name = "all"; # gets run as root anyways so can log in
|
|
# }
|
|
# ];
|
|
|
|
};
|
|
}
|