Traefik¶
Traefik is a modern reverse proxy and load balancer that automatically discovers services via Docker labels and handles TLS certificate management.
Why¶
Exposing 20+ services to the network without a reverse proxy would mean managing individual ports, TLS certificates, and authentication for each one. Traefik consolidates all of this — every service gets a clean https://<app>.${DOMAINNAME} URL with automatic Let's Encrypt certificates via Cloudflare DNS challenge. Adding a new service to Traefik requires only Docker labels in the compose file, not proxy configuration changes.
Compose File¶
- compose.yaml
- compose.svlazext.yaml — Azure external VM override
Access¶
| URL | Description |
|---|---|
https://traefik.${DOMAINNAME} |
Dashboard (Traefik forward-auth) |
Architecture¶
- Image: traefik (official)
- User/Group:
3100:3100(svc-app-traefik) - Networks: Joins every service's frontend network individually for per-service isolation (see Architecture)
- Ports:
80(HTTP → HTTPS redirect),443(HTTPS),8444(internal monitoring entrypoint — not published),8082(internal metrics entrypoint — not published) - Reverse proxy: Self-proxied dashboard with
chain-auth@filemiddleware
Key Features¶
- Automatic TLS: Wildcard certificate for
*.${DOMAINNAME}via Cloudflare DNS challenge (dns-cloudflareresolver) - Docker provider: Auto-discovers services from Docker labels via socket proxy
- Per-service networks: Each service gets its own frontend network — containers can only talk to Traefik, not to each other
- Monitoring entrypoint: Port 8444 with IP allowlist restricted to the
gatus-frontendsubnet for auth-free health checks - Metrics entrypoint: Port 8082 with IP allowlist restricted to the
alloy-frontendsubnet — Prometheus scrape target for Alloy (per-router / per-service / per-entrypoint labels enabled)
Services¶
| Container | Role |
|---|---|
traefik-init |
One-shot init: creates acme.json, chowns ./data/acme to 3100:3100, sets 600 permissions |
traefik |
Reverse proxy — routes traffic to all services, manages TLS certificates |
traefik-docker-proxy |
LinuxServer socket-proxy — read-only Docker API access (CONTAINERS=1) |
Config Structure¶
| Path | Purpose |
|---|---|
config/traefik.yml |
Static configuration — entrypoints, providers, certificate resolvers |
config/rules/middlewares.yml |
Middleware chains (chain-auth, chain-no-auth, rate limiting, headers, IP allowlists) |
data/acme/acme.json |
Let's Encrypt certificate store (runtime, 600 permissions) |
Multi-Server Deployment¶
Traefik runs on multiple servers with compose overrides:
- svlnas (TrueNAS) — primary instance, joins all service frontend networks
- svlazext — Azure VM, joins AdGuard and public app backend frontend networks
Secrets¶
Managed via secret.sops.env (SOPS-encrypted, decrypted to .env at deploy time):
DOMAINNAME— base domain for routing and wildcard certificateCF_DNS_API_TOKEN— Cloudflare API token for DNS challenge TLS certificate issuance
First-Run Setup¶
- Create the dataset
vm-pool/apps/services/traefikin TrueNAS - Create a
svc-app-traefikgroup (GID 3100) and user (UID 3100) on the TrueNAS host - Create a Cloudflare API token with
Zone:DNS:Editpermissions for your domain - Set
CF_DNS_API_TOKENandDOMAINNAMEinsecret.sops.env - Deploy — Traefik requests a wildcard certificate on first start (check
docker logs traefikfor ACME status) - Point your domain's DNS to the host IP (or use split-horizon via AdGuard/Unbound)
Upgrade Notes¶
No special upgrade procedures. Traefik handles configuration changes gracefully on restart. Check the Traefik migration guides when upgrading across major versions (e.g. v2 → v3). Image updates are managed by Renovate.