{ config, lib, ... }: let # Import router and service declarations grouped in files infraRouters = import ./configuration/infra/routers.nix; infraServices = import ./configuration/infra/services.nix; monitoringRouters = import ./configuration/monitoring/routers.nix; monitoringServices = import ./configuration/monitoring/services.nix; mediaRouters = import ./configuration/media-center/routers.nix; mediaServices = import ./configuration/media-center/services.nix; photosRouters = import ./configuration/photos/routers.nix; photosServices = import ./configuration/photos/services.nix; authRouters = import ./configuration/auth/routers.nix; authServices = import ./configuration/auth/services.nix; miscRouters = import ./configuration/misc/routers.nix; miscServices = import ./configuration/misc/services.nix; middlewares = import ./configuration/middlewares.nix; staticConfig = import ./configuration/static.nix; # Combine all routers and services from groups allRouters = lib.foldl' (acc: routers: acc // routers) {} [ infraRouters monitoringRouters mediaRouters photosRouters authRouters miscRouters ]; allServices = lib.foldl' (acc: services: acc // services) {} [ infraServices monitoringServices mediaServices photosServices authServices miscServices ]; in { services.traefik = { enable = true; environmentFiles = [config.sops.secrets."traefik-env".path]; staticConfigOptions = staticConfig; dynamicConfigOptions = { # HTTP configuration (your existing setup) http = { routers = allRouters; services = allServices; middlewares = middlewares; serversTransports = { insecureTransport = { insecureSkipVerify = true; }; }; }; tcp = { routers = { caddy-fallback = { rule = "HostSNI(`*`)"; # Matches any SNI service = "caddy-tls"; entryPoints = ["websecure"]; priority = 1; # Lowest priority - only if no HTTP router matches tls = { passthrough = true; }; }; }; services = { caddy-tls = { loadBalancer = { servers = [ { address = "sandbox.lab:443"; } ]; }; }; }; }; }; }; }