/root/traefik ├── .env ├── compose.yml ├── services │ ├── common │ │ ├── headers.yml │ │ └── middlewares.yml │ ├── photos.yml │ ├── server.yml │ └── vault.yml ├── template.yml └── traefik.yml Environment variables DOMAIN=potat.dev ACME_EMAIL=user@example.com CF_DNS_API_TOKEN=cfut_abc123 Token must have the following permissions:
- Zone / Zone / Read
- Zone / DNS / Edit If you are getting failed to create TXT record or context deadline exceeded error - uncomment timeouts section Source: https://go-acme.github.io/lego/dns/cloudflare Docker Compose configuration services: traefik: image: traefik:v3.7 container_name: traefik restart: unless-stopped security_opt:
- no-new-privileges:true env_file:
- .env command:
- "--entryPoints.websecure.http.tls.domains[0].main=${DOMAIN}"
- "--entryPoints.websecure.http.tls.domains[0].sans=*.${DOMAIN}"
ports:
- "80:80"
- "443:443"
volumes:
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./services:/etc/traefik/services:ro
- certs:/certs
volumes: certs: name: traefik_certs Domain settings are configured here because static configuration does not support environment variable substitution, whereas this method does. Static configuration is being merged together from the traefik.yml file and these parameters If you need an additional domain, add DOMAIN_SECONDARY to the .env file and add two more lines using domains[1] Warning Traefik v2 allowed you to write entryPoints as entrypoints , but v3 no longer does Static configuration, also known as Install configuration global: checkNewVersion: true sendAnonymousUsage: false api: dashboard: true insecure: false log: level: INFO entryPoints: web: address: ":80" asDefault: false http: redirections: entryPoint: to: websecure scheme: https websecure: address: ":443" asDefault: true http: tls: certResolver: cloudflare providers: file: directory: "/etc/traefik/services" watch: true certificatesResolvers: cloudflare: acme: storage: "/certs/acme.json" dnsChallenge: provider: cloudflare propagation: delayBeforeChecks: 10s resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
- "1.0.0.1:53"
- "8.8.4.4:53"
serversTransport: insecureSkipVerify: true insecureSkipVerify allows using insecure URLs withhttps:// protocol and missing SSL certs (e.q. Proxmox)disablePropagationCheck skips the DNS propagation checks before notifying ACME that the DNS challenge is readywebsecure.asDefault allows you to avoid specifying an entry point for each route Service configuration template
{{ $app := "app" }}
{{ $url := "http://10.0.10.XX:80" }}
http: routers:
{{ $app }}-router:
rule: Host(`{{ $app }}.{{ env "DOMAIN" }}`)
service: "{{ $app }}-service"
middlewares:
- "secure-headers" services: {{ $app }}-service: loadBalancer: servers:
- url: "{{ $url }}" passHostHeader: true How to use:
- Run cp template.yml services/service.yml to deploy new service - Edit $app and$url variables -$app will be your subdomain - Custom middleware sections can be removed How this works: Traefik uses Go text/template engine to parse expressions in dynamic configuration Example configuration for Proxmox
{{ $app := "server" }}
{{ $url := "https://10.0.10.42:8006" }}
http: routers:
{{ $app }}-router:
rule: Host(`{{ $app }}.{{ env "DOMAIN" }}`)
service: "{{ $app }}-service"
middlewares:
- "secure-headers" services: {{ $app }}-service: loadBalancer: servers:
- url: "{{ $url }}" passHostHeader: true Common secure headers configuration http: middlewares: secure-headers: headers: stsSeconds: 31536000 stsIncludeSubdomains: true forceSTSHeader: true contentTypeNosniff: true browserXssFilter: true customFrameOptionsValue: SAMEORIGIN