{ config, lib, pkgs, ... }: let magentaData = import ../data.secret.nix; dataDir = "/var/lib/traefik"; traefikCfg = config.services.traefik; user = "traefik"; group = "traefik"; dynamicConfigFile = pkgs.runCommand "config.toml" { buildInputs = [ pkgs.remarshal ]; preferLocalBuild = true; } '' remarshal -if json -of toml \ < ${pkgs.writeText "dynamic_config.json" (builtins.toJSON traefikCfg.dynamicConfigOptions)} \ > $out ''; staticConfigFile = pkgs.runCommand "config.toml" { buildInputs = [ pkgs.remarshal ]; preferLocalBuild = true; } '' remarshal -if json -of toml \ < ${ pkgs.writeText "static_config.json" (builtins.toJSON (lib.recursiveUpdate traefikCfg.staticConfigOptions { providers.file.filename = "${dynamicConfigFile}"; })) } \ > $out ''; mirrorVolume = path: "${path}:${path}"; in { networking.firewall.allowedTCPPorts = [ 80 443 8080 ]; users.users.${user} = { isSystemUser = true; createHome = true; home = dataDir; inherit group; }; users.groups.${group} = { }; users.groups.docker.members = [ user ]; systemd.tmpfiles.rules = [ "d '${dataDir}' 0700 ${user} ${group} - -" ]; age.secrets.traefik-dashboard-basicauth-users = { file = ../../../../secrets/traefik-dashboard-basicauth-users.age; owner = user; inherit group; }; virtualisation.docker.stacks.traefik = { networks.traefik_public.external = true; services.traefik = { image = "traefik:v2.9"; command = [ "--configFile=${staticConfigFile}" ]; ports = [ "80:80" "443:443" "8080:8080" ]; extra_hosts = [ "host.docker.internal:host-gateway" ]; networks = [ "traefik_public" ]; volumes = [ "${mirrorVolume "/var/run/docker.sock"}:ro" "${mirrorVolume dataDir}" "${mirrorVolume staticConfigFile}:ro" "${mirrorVolume dynamicConfigFile}:ro" "${mirrorVolume config.age.secrets.traefik-dashboard-basicauth-users.path}:ro" ]; deploy = { placement.constraints = [ "node.role==manager" ]; update_config.order = "start-first"; }; }; }; services.traefik = { staticConfigOptions = { entryPoints = { http = { address = ":80"; http.redirections.entryPoint = { to = "https"; scheme = "https"; }; }; https.address = ":443"; dashboard.address = ":8080"; }; api = { }; log = { }; accessLog = { }; certificatesResolvers.le.acme = { storage = "${dataDir}/acme.json"; email = "dmitriy@pleshevski.ru"; tlschallenge = true; }; providers.docker = { network = "traefik_public"; constraints = "Label(`traefik.constraint-label`, `${config.networking.hostName}_public`)"; exposedByDefault = false; swarmMode = true; }; }; dynamicConfigOptions.http = { routers.to_traefik_dashboard = { rule = "Host(`${magentaData.addr}`)"; entryPoints = [ "dashboard" ]; middlewares = [ "traefik_dashboard_auth" ]; service = "api@internal"; }; middlewares = { traefik_dashboard_auth.basicAuth = { usersFile = config.age.secrets.traefik-dashboard-basicauth-users.path; }; }; }; }; }