Files
nix-config/modules/nixos/services/traefik/default.nix
mjallen18 92b6e7a822 caddy
2026-02-11 22:23:00 -06:00

370 lines
10 KiB
Nix
Executable File

{
config,
lib,
namespace,
...
}:
with lib;
let
cfg = config.${namespace}.services.traefik;
# Process reverseProxies into service and router configurations
reverseProxyServiceConfigs =
let
makeService = reverseProxy: nameValuePair reverseProxy.service.name reverseProxy.service.config;
in
listToAttrs (map makeService cfg.reverseProxies);
reverseProxyRouterConfigs =
let
makeRouter = reverseProxy: nameValuePair reverseProxy.router.subdomain reverseProxy.router.config;
in
listToAttrs (map makeRouter cfg.reverseProxies);
domain = "mjallen.dev";
# Forward services
authUrl = "http://localhost:9000/outpost.goauthentik.io";
cacheUrl = "http://localhost:9012";
hassUrl = "http://nuc-nixos.local:8123";
# Plugins
traefikPlugins = {
bouncer = {
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin";
version = "v1.4.5";
};
geoblock = {
moduleName = "github.com/PascalMinder/geoblock";
version = "v0.2.5";
};
};
# Ports
httpPort = 80;
httpsPort = 443;
traefikPort = 8080;
metricsPort = 8082;
forwardPorts = [
httpPort
httpsPort
traefikPort
metricsPort
];
# misc
letsEncryptEmail = "jalle008@proton.me";
configDir = "/media/nas/main/appdata";
in
{
imports = [
./options.nix
./sops.nix
];
config = mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = forwardPorts;
allowedUDPPorts = forwardPorts;
};
services.traefik = {
enable = true;
dataDir = "${configDir}/traefik";
group = "jallen-nas"; # group;
environmentFiles = [ config.sops.templates."traefik.env".path ];
static = {
# dir = "${configDir}/traefik";
settings = {
entryPoints = {
web = {
address = ":${toString httpPort}";
asDefault = true;
http.redirections.entrypoint = {
to = "websecure";
scheme = "https";
};
};
websecure = {
address = ":${toString httpsPort}";
asDefault = true;
http.tls.certResolver = "letsencrypt";
};
metrics = {
address = ":${toString metricsPort}"; # Port for metrics
};
};
log = {
level = "INFO";
};
metrics = {
prometheus = {
entryPoint = "metrics";
addEntryPointsLabels = true;
addServicesLabels = true;
buckets = [
0.1
0.3
1.2
5.0
]; # Response time buckets
};
};
certificatesResolvers.letsencrypt.acme = {
email = letsEncryptEmail;
storage = "${config.services.traefik.dataDir}/acme.json";
dnsChallenge = {
provider = "cloudflare";
resolvers = [
"1.1.1.1:53"
"8.8.8.8:53"
];
};
};
# Access the Traefik dashboard on <Traefik IP>:8080
api = {
dashboard = true;
insecure = true;
};
experimental = {
plugins = traefikPlugins;
};
};
};
dynamic = {
dir = "/run/traefik";
files = {
"serversTransports".settings.http = {
serversTransports = {
internal-https = {
insecureSkipVerify = true;
};
http1 = {
serverName = "localhost";
disableHTTP2 = true;
};
};
};
"middlewares-authentik".settings.http = {
middlewares = {
authentik = {
forwardAuth = {
tls.insecureSkipVerify = true;
address = "${authUrl}/auth/traefik";
trustForwardHeader = true;
authResponseHeaders = [
"X-authentik-username"
"X-authentik-groups"
"X-authentik-email"
"X-authentik-name"
"X-authentik-uid"
"X-authentik-jwt"
"X-authentik-meta-jwks"
"X-authentik-meta-outpost"
"X-authentik-meta-provider"
"X-authentik-meta-app"
"X-authentik-meta-version"
];
};
};
};
};
"middlewares-crowdsec".settings.http = {
middlewares = {
crowdsec = {
plugin = {
bouncer = {
enabled = true;
crowdsecLapiKeyFile = config.sops.secrets."jallen-nas/traefik/crowdsec/lapi-key".path;
crowdsecLapiScheme = "http";
crowdsecLapiHost = "localhost:8181";
crowdsecLapiPath = "/";
crowdsecLapiTLSInsecureVerify = false;
crowdsecCapiMachineIdFile = config.sops.secrets."jallen-nas/traefik/crowdsec/capi-machine-id".path;
crowdsecCapiPasswordFile = config.sops.secrets."jallen-nas/traefik/crowdsec/capi-password".path;
crowdsecCapiScenarios = [ ];
};
};
};
};
};
"middlewares-geoblock".settings.http = {
middlewares = {
whitelist-geoblock = {
plugin = {
geoblock = {
silentStartUp = false;
allowLocalRequests = true;
logLocalRequests = false;
logAllowedRequests = false;
logApiRequests = false;
api = "https://get.geojs.io/v1/ip/country/{ip}";
apiTimeoutMs = 500;
cacheSize = 25;
forceMonthlyUpdate = true;
allowUnknownCountries = false;
unknownCountryApiResponse = "nil";
blackListMode = false;
countries = [
"CA"
"US"
];
};
};
};
};
};
"middlewares-ipallowlist".settings.http = {
middlewares = {
internal-ipallowlist = {
ipAllowList = {
sourceRange = [
"127.0.0.1/32"
"10.0.1.0/24"
];
};
};
};
};
"services-auth".settings.http = {
services = {
auth.loadBalancer.servers = [
{
url = authUrl;
}
];
};
};
"services-cache".settings.http = {
services = {
cache.loadBalancer = {
servers = [
{
url = cacheUrl;
}
];
serversTransport = "http1";
};
};
};
"services-nginx".settings.http = {
services = {
nginx.loadBalancer.servers = [
{
url = "http://localhost:8188";
}
];
};
};
"services-generated".settings.http = reverseProxyServiceConfigs;
"routers-auth".settings.http = {
routers = {
auth = {
entryPoints = [ "websecure" ];
rule = "HostRegexp(`{subdomain:[a-z]+}.mjallen.dev`) && PathPrefix(`/outpost.goauthentik.io/`)";
service = "auth";
middlewares = [
"crowdsec"
"whitelist-geoblock"
];
priority = 15;
tls.certResolver = "letsencrypt";
};
};
};
"routers-matrix2".settings.http = {
routers = {
matrix2 = {
entryPoints = [ "websecure" ];
rule = "Host(`matrix.mjallen.dev`) && PathPrefix(`/.well-known/matrix/`)";
service = "nginx";
middlewares = [
"crowdsec"
"whitelist-geoblock"
];
priority = 1;
tls.certResolver = "letsencrypt";
};
};
};
"routers-matrix3".settings.http = {
routers = {
matrix3 = {
entryPoints = [ "websecure" ];
rule = "Host(`mjallen.dev`) && PathPrefix(`/.well-known/matrix/`)";
service = "nginx";
middlewares = [
"crowdsec"
"whitelist-geoblock"
];
priority = 1;
tls.certResolver = "letsencrypt";
};
};
};
"routers-cache".settings.http = {
routers = {
cache = {
entryPoints = [ "websecure" ];
rule = "Host(`cache.${domain}`)";
service = "cache";
middlewares = [ ];
priority = 10;
tls.certResolver = "letsencrypt";
};
};
};
"home-assistant".settings.http = {
services = {
hass.loadBalancer.servers = [
{
url = hassUrl;
}
];
};
routers = {
hass = {
entryPoints = [ "websecure" ];
rule = "Host(`hass.${domain}`)";
service = "hass";
middlewares = [
"crowdsec"
"whitelist-geoblock"
# "authentik"
];
priority = 10;
tls.certResolver = "letsencrypt";
};
};
};
"routers-generated".settings.http = reverseProxyRouterConfigs;
};
};
};
};
}