This episode covers comprehensive security: least privilege principles, securing the dashboard, API, and metrics endpoints, strong TLS configuration with ciphers and HSTS, container security with non-root and read-only filesystems, and secret management with Docker secrets and Kubernetes secrets.

Traefik is the gateway for all traffic — the most attractive target for attackers. Episode 28 covers security hardening: locking down every side of Traefik, from public exposure down to the smallest container attack surface. None of the steps here are optional for a public deployment.
The approach is layered: least privilege principles, securing administrative endpoints, strong TLS, containers that cannot be written carelessly, and secrets that never touch config files. After this episode, your Traefik will be far harder to breach.
:ro and only if the provider needs it.A Traefik dashboard without authentication is an open invitation to map the entire infrastructure. Secure it with a BasicAuth middleware and place it on an internal entrypoint:
http:
routers:
dashboard:
rule: "Host(`traefik.localhost`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
entrypoints:
- dashboard
service: api@internal
middlewares:
- admin-auth
tls: {}
middlewares:
admin-auth:
basicAuth:
users:
- "admin:$2y$05$0UvReaDF8s0BbQpqBFBp8e1gV6Q2Y0hH9o5QyTq3a4j7kLmZxS2C"The password hash is generated with htpasswd (episode 9). Note that the entrypoint used is dashboard, isolated on an internal port — a combination of network isolation and authentication.
The metrics and ping endpoints must also be protected:
ufw deny 8080
ufw deny 9100
ufw deny 8082
ufw allow 80
ufw allow 443
ufw enableThe firewall rules above close the dashboard, metrics, and health ports from the internet, leaving only 80 and 443. The ufw commands use UFW — adjust for your own firewall. For Kubernetes, the same endpoints are locked down with a NetworkPolicy.
Apply a TLSOption that rejects old protocols:
http:
tlsOptions:
secure:
minVersion: VersionTLS12
maxVersion: VersionTLS13
sniStrict: trueComplete it with HSTS from episode 10 and the HTTP to HTTPS redirect from episode 11. This combination forces all traffic to modern TLS with correct certificates. Do not forget: acme.json must be backed up, and config files must not contain secrets.
Run Traefik with the minimum privilege possible:
services:
traefik:
image: traefik:v3
user: "65532:65532"
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/etc/traefik/acme.jsonuser: "65532:65532": runs as a non-root user.read_only: true: the filesystem cannot be written — only a writable mount for acme.json.cap_drop: ALL then cap_add: NET_BIND_SERVICE: remove all capabilities except binding ports below 1024.If Traefik uses the API dashboard, note that the internal dashboard entrypoint can also be reached between containers on the same network — the combination of network isolation and BasicAuth is still required.
Secrets such as Cloudflare tokens or BasicAuth passwords must not be typed in traefik.yml or a compose file that goes into git:
.env.The golden rule: if a secret shows up in git diff output, move it to a secret management mechanism immediately.
Tip
Enable security scanning in your pipeline: trivy image traefik:v3 before deploying. CVEs in the Traefik image itself are rare, but making scanning a habit keeps every layer under control.
Key takeaways:
In episode 29 next we will cover plugins & extensibility — the Traefik plugin ecosystem, popular plugins such as GeoIP and advanced rate limiting, the Go plugin development architecture with plugin.toml, and the plugin installation and versioning process.