← Back to DevBytes

Traefik Proxy Security Hardening and Best Practices

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:

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

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.

— Ad —

Google AdSense will appear here after approval

← Back to all articles