{ config, lib, pkgs, ... }: let cfg = config.homelab.apps.traefik; port = 8080; in { options.homelab.apps.traefik = { enable = lib.mkEnableOption "Traefik Reverse Proxy"; sharedNetworkName = lib.mkOption { type = lib.types.str; default = "traefik"; description = "The name of the shared network to connect the container to."; }; }; config = lib.mkIf cfg.enable { homelab.virtualisation.containers.enable = true; # Make sure the Docker network exists. systemd.services."docker-${cfg.sharedNetworkName}-create-network" = { description = "Create Docker network for ${cfg.sharedNetworkName}"; requiredBy = [ "docker-traefik.service" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' if ! ${pkgs.docker}/bin/docker network ls | grep -q ${cfg.sharedNetworkName}; then ${pkgs.docker}/bin/docker network create ${cfg.sharedNetworkName} fi ''; }; virtualisation.oci-containers.containers.traefik = { hostname = "traefik"; image = "traefik:v3.4.3"; autoStart = true; ports = [ "80:80/tcp" "443:443/tcp" "${toString port}:${toString port}/tcp" # Web UI (enabled by --api.insecure=true) ]; extraOptions = [ "--network=${cfg.sharedNetworkName}" ]; environmentFiles = [ /home/admin/.cloudflare.secret ]; cmd = [ "--api.insecure=true" # Add Docker provider "--providers.docker=true" "--providers.docker.exposedByDefault=false" # Add web entrypoint "--entrypoints.web.address=:80/tcp" "--entrypoints.web.http.redirections.entrypoint.to=websecure" "--entrypoints.web.http.redirections.entrypoint.scheme=https" # Add websecure entrypoint "--entrypoints.websecure.address=:443/tcp" "--entrypoints.websecure.http.tls=true" "--entrypoints.websecure.http.tls.certResolver=letsencrypt" "--entrypoints.websecure.http.tls.domains[0].main=depeuter.dev" "--entrypoints.websecure.http.tls.domains[0].sans=*.depeuter.dev" "--entrypoints.websecure.http.tls.domains[1].sans=*.${config.networking.hostName}.depeuter.dev" # Certificates "--certificatesresolvers.letsencrypt.acme.dnschallenge=true" "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare" "--certificatesresolvers.letsencrypt.acme.email=tibo.depeuter@telenet.be" "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json" ]; volumes = [ "letsencryp:/letsencrypt" "/var/run/docker.sock:/var/run/docker.sock:ro" ]; labels = { "traefik.enable" = "true"; "traefik.http.routers.traefik.rule" = "Host(`traefik.${config.networking.hostName}.depeuter.dev`)"; "traefik.http.services.traefik.loadbalancer.server.port" = toString port; }; }; }; }