Traefik Proxy Security Hardening and Best Practices
Traefik is one of the most popular cloud-native reverse proxies and load balancers, widely adopted in Docker, Kubernetes, and bare-metal environments. While Traefik ships with sensible defaults, a production deployment requires deliberate security hardening. This tutorial walks you through the most important security configurations, from TLS and authentication to rate limiting, network isolation, and observability. By the end, you will have a hardened Traefik setup that resists common web attacks and limits the blast radius of any compromise.
What Is Traefik Security Hardening?
Security hardening is the process of reducing a system's attack surface by disabling unnecessary features, enforcing strong cryptographic standards, restricting access, and adding defensive layers such as rate limiting and Web Application Firewall (WAF) rules. With Traefik, hardening involves configuration across several layers: the entrypoints, the routers, the middleware chain, the TLS settings, the dashboard/API exposure, and the underlying host environment.
Why It Matters
A reverse proxy sits at the edge of your infrastructure, making it a prime target for attackers. A misconfigured Traefik instance can leak internal service metadata, expose an unauthenticated dashboard, accept weak TLS connections, or become an open relay for abuse. Hardening Traefik protects not only the proxy itself but every service behind it. It also helps you meet compliance requirements such as PCI-DSS, HIPAA, and SOC 2, which mandate encryption in transit, access controls, and audit logging.
1. Securing the Traefik Dashboard and API
By default, Traefik can expose a dashboard and a REST API. In production, these should never be publicly accessible without authentication. The safest approach is to bind the dashboard to a localhost or internal-only entrypoint and protect it with basic authentication.
Disabling the Dashboard Entirely
If you do not need the dashboard in production, disable it entirely to reduce attack surface:
# traefik.yml (static configuration)
api:
dashboard: false
insecure: false
Protecting the Dashboard with Basic Auth
If you keep the dashboard, expose it only through a secured router with a basic auth middleware. Generate a hashed password using htpasswd:
htpasswd -nbB admin "YourStrongPasswordHere"
# Output: admin:$2y$05$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Then configure the router and middleware in your dynamic configuration:
# dynamic-configuration.yml
http:
routers:
dashboard:
rule: "Host(`traefik.internal.example.com`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
entryPoints:
- websecure
middlewares:
- dashboard-auth
- dashboard-allowlist
service: api@internal
tls:
certResolver: letsencrypt
middlewares:
dashboard-auth:
basicAuth:
users:
- "admin:$2y$05$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
removeHeader: true
dashboard-allowlist:
ipAllowList:
sourceRange:
- "10.0.0.0/8"
- "192.168.1.0/24"
The removeHeader: true option strips the Authorization header before forwarding to the internal API, preventing credential leakage to backend services.
2. Enforcing TLS and HTTPS
Traefik supports automatic TLS certificate generation through Let's Encrypt. The first hardening step is to redirect all HTTP traffic to HTTPS and configure strong cipher suites.
HTTP to HTTPS Redirect
# traefik.yml (static configuration)
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
domains:
- main: "example.com"
sans:
- "*.example.com"
Strong TLS Configuration
Disable legacy TLS versions and weak ciphers. The following configuration enforces TLS 1.2 and 1.3 only, with modern cipher suites:
# traefik.yml
entryPoints:
websecure:
address: ":443"
http:
tls:
options: modern
tls:
options:
modern:
minVersion: VersionTLS12
maxVersion: VersionTLS13
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
The sniStrict: true option rejects requests where the Server Name Indication does not match any configured certificate, preventing hostname probing attacks.
Configuring HSTS
HTTP Strict Transport Security tells browsers to always use HTTPS. Add it through a middleware:
http:
middlewares:
secure-headers:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: "strict-origin-when-cross-origin"
contentSecurityPolicy: "default-src 'self'; script-src 'self'; object-src 'none'"
Apply this middleware to all public routers as a default security baseline.
3. Authentication and Authorization
Traefik provides several authentication middlewares: BasicAuth, DigestAuth, ForwardAuth, and OAuth integration through external providers. For production, ForwardAuth with an external identity provider is the most robust approach.
ForwardAuth with an External Provider
http:
middlewares:
my-auth:
forwardAuth:
address: "https://auth.example.com/authorize"
authResponseHeaders:
- "X-Auth-User"
- "X-Auth-Role"
authRequestHeaders:
- "Accept"
- "Cookie"
trustForwardHeader: true
tls:
insecureSkipVerify: false
The external authorization service validates each request and returns either a 200 OK or a 401/403 response. This pattern integrates cleanly with OAuth2 Proxy, Authelia, or custom identity services.
4. Rate Limiting and Brute Force Protection
Rate limiting protects your services from brute force attacks, credential stuffing, and denial-of-service attempts. Traefik's rateLimit middleware caps requests per source IP.
http:
middlewares:
rate-limit:
rateLimit:
average: 100
period: "1s"
burst: 200
sourceCriterion:
ipStrategy:
depth: 2
The depth: 2 setting tells Traefik to use the second-to-last IP from the X-Forwarded-For header, which is appropriate when Traefik sits behind a trusted CDN or cloud load balancer. Adjust the depth based on your network topology to avoid spoofed IP-based bypass.
Combining Rate Limiting with Retry Protection
http:
routers:
api-router:
rule: "Host(`api.example.com`)"
entryPoints:
- websecure
middlewares:
- rate-limit
- secure-headers
- retry
service: api-service
tls:
certResolver: letsencrypt
middlewares:
retry:
retries: 3
5. Request Size Limits and Body Filtering
Limiting request body size prevents large payload attacks and file upload abuse. Use the buffering middleware to enforce size limits:
http:
middlewares:
buffer-limit:
buffering:
maxRequestBodyBytes: 1048576
memRequestBodyBytes: 2097152
retryExpression: "IsNetworkError() && Attempts() <= 2"
This configuration rejects any request body larger than 1 MB, protecting upstream services from memory exhaustion attacks.
6. IP Allowlisting and Denylisting
For internal services or admin endpoints, restrict access by IP range. Traefik supports both allowlists and denylists:
http:
middlewares:
internal-only:
ipAllowList:
sourceRange:
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
blocklist:
ipAllowList:
sourceRange:
- "203.0.113.0/24"
For more dynamic denylisting, combine Traefik with a Fail2Ban sidecar or use the ForwardAuth pattern to consult a threat intelligence service.
7. Securing the Docker Provider
When using Traefik with Docker, restrict the Docker socket access and use label-based configuration carefully. Never expose the Docker socket without restrictions.
# docker-compose.yml
services:
traefik:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=proxy"
- "--providers.docker.constraints=Label(`traefik.enable`,`true`)"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./acme.json:/acme.json:ro
ports:
- "80:80"
- "443:443"
networks:
- proxy
restart: unless-stopped
Key hardening points in this configuration:
exposedbydefault=falseprevents accidental exposure of containers that lack explicit Traefik labels.constraintsensures only containers withtraefik.enable=trueare considered.- The Docker socket is mounted read-only.
- The ACME certificate file is mounted read-only after initial creation.
- Traefik is on a dedicated
proxynetwork, isolating it from internal service networks.
Protecting the ACME Certificate File
The acme.json file contains private keys for your TLS certificates. It must have strict file permissions:
touch acme.json
chmod 600 acme.json
chown root:root acme.json
Traefik will refuse to start if the permissions are too permissive, which is a useful safety mechanism.
8. Running Traefik as a Non-Root User
By default, Traefik listens on ports 80 and 443, which require root privileges on Linux. To run as a non-root user, use port redirection or capability management:
# docker-compose.yml
services:
traefik:
image: traefik:v3.0
user: "65532:65532"
command:
- "--entryPoints.web.address=:8080"
- "--entryPoints.websecure.address=:8443"
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
Then use iptables or your cloud provider's load balancer to redirect external ports 80 and 443 to 8080 and 8443 internally. The no-new-privileges flag prevents privilege escalation, and read_only makes the container filesystem immutable.
9. Logging and Observability
Security hardening is incomplete without monitoring. Configure Traefik to log access events, errors, and TLS handshake details. Send logs to a centralized system for analysis and alerting.
# traefik.yml
accessLog:
filePath: "/var/log/traefik/access.log"
format: json
bufferingSize: 100
filters:
statusCodes:
- "400-599"
retryAttempts: true
minDuration: "100ms"
fields:
defaultMode: keep
headers:
defaultMode: redact
names:
User-Agent: keep
Referer: keep
Authorization: drop
Cookie: drop
log:
level: INFO
format: json
filePath: "/var/log/traefik/traefik.log"
Notice the header redaction: sensitive headers like Authorization and Cookie are dropped from logs to prevent credential leakage in log aggregation systems.
Enabling Metrics for Security Monitoring
metrics:
prometheus:
addEntryPointsLabels: true
addServicesLabels: true
addRoutersLabels: true
entryPoint: metrics
entryPoints:
metrics:
address: ":9100"
Bind the metrics entrypoint to an internal-only interface and scrape it with Prometheus. Alert on spikes in 4xx and 5xx responses, which can indicate attack activity.
10. Best Practices Summary
- Never expose the Traefik dashboard or API without authentication and IP restrictions.
- Always redirect HTTP to HTTPS and enforce TLS 1.2+ with modern cipher suites.
- Apply security headers (HSTS, CSP, X-Frame-Options) globally through a default middleware chain.
- Use ForwardAuth with an external identity provider for production-grade authentication.
- Implement rate limiting on all public-facing routers to mitigate brute force and abuse.
- Limit request body sizes to prevent payload-based denial-of-service attacks.
- Set
exposedbydefault=falseon the Docker provider and use explicit labels. - Mount the Docker socket and ACME file read-only with strict file permissions.
- Run Traefik as a non-root user with dropped capabilities and a read-only filesystem.
- Redact sensitive headers from access logs and centralize log collection for auditing.
- Keep Traefik updated to the latest stable release to receive security patches promptly.
- Use a dedicated network for Traefik and avoid bridging it directly to internal service networks.
- Regularly review your router rules and middleware chains for unintended exposure.
Conclusion
Hardening Traefik is a layered effort that spans static configuration, dynamic routing rules, middleware chains, TLS settings, and container runtime constraints. By disabling unnecessary features, enforcing strong encryption, adding authentication and rate limiting, restricting network access, and maintaining robust logging, you transform Traefik from a capable reverse proxy into a secure edge gateway. Security is not a one-time task but an ongoing practice: review your configuration regularly, monitor traffic patterns for anomalies, and update Traefik promptly when new releases ship. With the patterns described in this tutorial, you have a solid foundation for running Traefik safely in production environments of any scale.