Traefik

Reverse proxy specialized for cloud-native environments. Enables dynamic configuration management through Docker and Kubernetes integration. Automatic service discovery and load balancing capabilities.

reverse-proxydockerkubernetesmicroservicescloud-nativeload-balancergo

Traefik Proxy

Traefik is a cloud-native reverse proxy and load balancer specialized for cloud-native environments. Through tight integration with Docker and Kubernetes, it automates dynamic service discovery and configuration management, providing an optimized design for microservices architectures.

Overview

Traefik is an HTTP reverse proxy and load balancer designed for microservices that automatically configures itself by integrating with existing infrastructure components. Unlike traditional reverse proxies that require manual configuration, Traefik uses service discovery to dynamically configure routing, eliminating the need for configuration updates and restarts when services are added, removed, or scaled.

Details

Traefik 2025 edition continues to establish itself as the leading cloud-native application proxy solution. With over 2 billion downloads and extensive adoption in production environments, Traefik has proven its reliability for managing complex distributed systems. The latest v3.4 series includes enhanced observability through expanded OpenTelemetry integration, improved security features, and advanced service discovery capabilities. Built in Go, Traefik provides high performance while maintaining simplicity in operation, making it capable of handling large, highly-complex deployments across public, private, and hybrid clouds.

Key Features

  • Dynamic Service Discovery: Automatic detection and configuration of services
  • Multi-Provider Support: Docker, Kubernetes, Consul, Etcd integration
  • Let's Encrypt Integration: Automatic SSL certificate management
  • Advanced Load Balancing: Multiple algorithms and health checking
  • Comprehensive Observability: Metrics, tracing, and access logs
  • Zero-Downtime Updates: Configuration changes without restarts

Pros and Cons

Pros

  • Revolutionary dynamic service discovery eliminates manual configuration overhead
  • Exceptional cloud-native integration with Kubernetes, Docker, and service meshes
  • Zero-downtime configuration updates ensuring high availability during deployments
  • Comprehensive observability features with OpenTelemetry, Prometheus, and Jaeger support
  • Advanced load balancing capabilities including weighted routing and traffic mirroring
  • Extensive middleware ecosystem for authentication, rate limiting, and security
  • Production-proven scalability handling billions of requests across diverse environments

Cons

  • Steeper learning curve compared to traditional reverse proxies for beginners
  • Complex configuration scenarios may require deep understanding of providers and CRDs
  • Resource overhead higher than lightweight alternatives due to dynamic discovery features
  • Debugging routing issues can be challenging in large, complex environments
  • Limited standalone static configuration options compared to traditional proxies
  • Dependency on orchestrator APIs may introduce single points of failure

Reference Pages

Code Examples

Installation and Basic Setup

# Install with Docker
docker run -d \
  --name traefik \
  -p 80:80 \
  -p 443:443 \
  -p 8080:8080 \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  traefik:v3.4 \
  --api.insecure=true \
  --providers.docker=true \
  --providers.docker.exposedbydefault=false \
  --entrypoints.web.address=:80 \
  --entrypoints.websecure.address=:443

# Install with Kubernetes Helm
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik

# Install binary on Linux
curl -L https://github.com/traefik/traefik/releases/download/v3.4.1/traefik_v3.4.1_linux_amd64.tar.gz | tar -xzf -
sudo mv traefik /usr/local/bin/
sudo chmod +x /usr/local/bin/traefik

# Verify installation
traefik version

Basic Configuration (traefik.yml)

# Static configuration
global:
  checkNewVersion: false
  sendAnonymousUsage: false

api:
  dashboard: true
  debug: true

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entrypoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"
    http3:
      enabled: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: traefik-network
  file:
    filename: /etc/traefik/dynamic.yml
    watch: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /certs/acme.json
      httpChallenge:
        entryPoint: web
      dnsChallenge:
        provider: cloudflare
        delayBeforeCheck: 60

log:
  level: INFO
  filePath: "/var/log/traefik/traefik.log"

accessLog:
  filePath: "/var/log/traefik/access.log"
  format: json

HTTPS Configuration and SSL Management

# ACME configuration for multiple certificate resolvers
certificatesResolvers:
  letsencrypt-http:
    acme:
      email: [email protected]
      storage: /certs/acme-http.json
      httpChallenge:
        entryPoint: web
  
  letsencrypt-dns:
    acme:
      email: [email protected]
      storage: /certs/acme-dns.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"
  
  letsencrypt-staging:
    acme:
      email: [email protected]
      storage: /certs/acme-staging.json
      caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      httpChallenge:
        entryPoint: web

# Dynamic configuration (dynamic.yml)
tls:
  options:
    default:
      minVersion: "VersionTLS12"
      maxVersion: "VersionTLS13"
      sslStrategies:
        - "tls.SniStrict"
      cipherSuites:
        - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
        - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"
        - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
        - "TLS_RSA_WITH_AES_256_GCM_SHA384"
      
    strict:
      minVersion: "VersionTLS13"
      sslStrategies:
        - "tls.SniStrict"
      clientAuth:
        caFiles:
          - /certs/ca.pem
        clientAuthType: RequireAndVerifyClientCert

# Custom certificates
  certificates:
    - certFile: /certs/custom.crt
      keyFile: /certs/custom.key
      stores:
        - default

Performance Optimization and Load Balancing

# Advanced load balancing configuration
http:
  services:
    api-load-balancer:
      loadBalancer:
        servers:
          - url: "http://api-1:3000"
          - url: "http://api-2:3000"
          - url: "http://api-3:3000"
        
        # Load balancing algorithm
        passHostHeader: true
        responseForwarding:
          flushInterval: 100ms
        
        healthCheck:
          path: /health
          interval: 30s
          timeout: 5s
          hostname: api.internal
          scheme: http
          headers:
            X-Health-Check: "traefik"
        
        # Sticky sessions
        sticky:
          cookie:
            name: "traefik-session"
            secure: true
            httpOnly: true
            sameSite: "lax"

# Weighted Round Robin
    weighted-service:
      weighted:
        services:
          - name: api-v1
            weight: 80
          - name: api-v2
            weight: 20

# Circuit breaker configuration
serversTransport:
  default:
    maxIdleConnsPerHost: 200
    forwardingTimeouts:
      dialTimeout: 30s
      responseHeaderTimeout: 60s
      idleConnTimeout: 90s
    
    # Connection pooling
    disableHTTP2: false
    
  custom:
    insecureSkipVerify: true
    rootCAs:
      - /certs/ca.pem
    certificates:
      - certFile: /certs/client.crt
        keyFile: /certs/client.key

Security Configuration and Middleware

# Security middleware configuration
http:
  middlewares:
    # Security headers
    security-headers:
      headers:
        frameDeny: true
        sslRedirect: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsSeconds: 31536000
        stsPreload: true
        customFrameOptionsValue: "SAMEORIGIN"
        customRequestHeaders:
          X-Forwarded-Proto: "https"
        customResponseHeaders:
          X-Robots-Tag: "noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex"
          server: ""

    # Rate limiting
    api-rate-limit:
      rateLimit:
        burst: 100
        period: 1m
        sourceCriterion:
          ipStrategy:
            depth: 2
            excludedIPs:
              - "127.0.0.1/32"
              - "192.168.0.0/16"

    # IP allowlist
    internal-only:
      ipAllowList:
        sourceRange:
          - "192.168.1.0/24"
          - "10.0.0.0/8"
          - "172.16.0.0/12"

    # Basic authentication
    basic-auth:
      basicAuth:
        users:
          - "admin:$2y$12$..."  # htpasswd generated hash
          - "user:$2y$12$..."
        realm: "Restricted Area"

    # Forward authentication
    oauth-auth:
      forwardAuth:
        address: "http://oauth2-proxy:4180"
        authResponseHeaders:
          - "X-Auth-User"
          - "X-Auth-Email"
          - "X-Auth-Groups"
        trustForwardHeader: true

    # Request/Response modification
    api-headers:
      headers:
        customRequestHeaders:
          X-API-Version: "v2"
          X-Client-ID: "traefik"
        customResponseHeaders:
          X-API-Server: "traefik-lb"
          Access-Control-Allow-Origin: "*"

  # Applying middleware to routes
  routers:
    secure-api:
      rule: "Host(`api.example.com`)"
      entryPoints:
        - websecure
      middlewares:
        - security-headers
        - api-rate-limit
        - oauth-auth
        - api-headers
      service: api-load-balancer
      tls:
        certResolver: letsencrypt-dns

Kubernetes Integration (IngressRoute)

# Traefik IngressRoute for Kubernetes
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: webapp-ingressroute
  namespace: production
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`app.example.com`)
      kind: Rule
      services:
        - name: webapp-service
          port: 80
          scheme: http
          strategy: RoundRobin
          weight: 100
          nativeLB: true
      middlewares:
        - name: security-headers
        - name: rate-limit
  tls:
    certResolver: letsencrypt
    domains:
      - main: app.example.com
        sans:
          - www.app.example.com

---
# Middleware definitions
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: security-headers
  namespace: production
spec:
  headers:
    frameDeny: true
    sslRedirect: true
    browserXssFilter: true
    contentTypeNosniff: true
    forceSTSHeader: true
    stsIncludeSubdomains: true
    stsSeconds: 31536000

---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: rate-limit
  namespace: production
spec:
  rateLimit:
    burst: 100
    period: 1m

---
# TCP routing for databases
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: postgres-tcp
  namespace: production
spec:
  entryPoints:
    - postgres-tcp
  routes:
    - match: HostSNI(`*`)
      services:
        - name: postgres-service
          port: 5432
          proxyProtocol:
            version: 2

---
# UDP routing for DNS
apiVersion: traefik.io/v1alpha1
kind: IngressRouteUDP
metadata:
  name: dns-udp
  namespace: kube-system
spec:
  entryPoints:
    - dns
  routes:
    - services:
        - name: coredns
          port: 53

Observability and Monitoring

# Comprehensive observability configuration
metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true
    addRoutersLabels: true
    buckets:
      - 0.1
      - 0.3
      - 1.2
      - 5.0
      - 10.0

tracing:
  otlp:
    http:
      endpoint: "http://jaeger:14268/api/traces"
      headers:
        Authorization: "Bearer token"
    grpc:
      endpoint: "jaeger:14250"
      insecure: true
  
  serviceName: "traefik"
  sampleRate: 1.0
  globalTags:
    environment: "production"
    datacenter: "us-east-1"

# Structured logging
log:
  level: INFO
  format: json
  filePath: "/var/log/traefik/traefik.log"

accessLog:
  format: json
  filePath: "/var/log/traefik/access.log"
  filters:
    statusCodes: ["400-499", "500-599"]
    retryAttempts: true
    minDuration: "10ms"
  fields:
    defaultMode: keep
    names:
      ClientUsername: drop
      ClientHost: keep
      ClientPort: drop
    headers:
      defaultMode: keep
      names:
        User-Agent: keep
        Authorization: drop
        Content-Type: keep

# Health check endpoints
ping:
  entryPoint: "traefik"

Production Deployment (Docker Compose)

# Production-ready docker-compose.yml
version: '3.8'

services:
  traefik:
    image: traefik:v3.4
    container_name: traefik
    restart: unless-stopped
    
    command:
      - "--configFile=/etc/traefik/traefik.yml"
    
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"  # HTTP/3
      - "8080:8080"    # Dashboard (secure in production)
      - "9100:9100"    # Metrics
    
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik:/etc/traefik:ro"
      - "traefik-certs:/certs"
      - "/var/log/traefik:/var/log/traefik"
    
    environment:
      - "CF_API_EMAIL=${CLOUDFLARE_EMAIL}"
      - "CF_DNS_API_TOKEN=${CLOUDFLARE_TOKEN}"
    
    networks:
      - traefik
      - monitoring
    
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth"
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$12$$..."
    
    healthcheck:
      test: ["CMD", "traefik", "healthcheck", "--ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  # Example application
  whoami:
    image: traefik/whoami:v1.8
    restart: unless-stopped
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

volumes:
  traefik-certs:
    external: true

networks:
  traefik:
    external: true
  monitoring:
    external: true

Kubernetes Production Deployment (Helm Values)

# values.yaml for production Helm deployment
image:
  tag: "v3.4.1"

deployment:
  kind: DaemonSet
  replicas: 3

service:
  type: LoadBalancer
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"

ports:
  web:
    redirectTo: websecure
  websecure:
    http3:
      enabled: true
    tls:
      enabled: true
  metrics:
    port: 9100

providers:
  kubernetesIngress:
    enabled: true
    ingressClass: traefik
    publishedService:
      enabled: true
  kubernetesCRD:
    enabled: true
    ingressClass: traefik
    allowCrossNamespace: true
  kubernetesGateway:
    enabled: true

certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /data/acme.json
      dnsChallenge:
        provider: route53
        delayBeforeCheck: 60s
        resolvers:
          - "1.1.1.1:53"
          - "8.8.8.8:53"

persistence:
  enabled: true
  size: 128Mi
  storageClass: "gp3"

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 1000m
    memory: 1Gi

securityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop: ["ALL"]
    add: ["NET_BIND_SERVICE"]
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  runAsUser: 65532

metrics:
  prometheus:
    service:
      enabled: true
    serviceMonitor:
      enabled: true
      namespace: monitoring

logs:
  general:
    level: INFO
  access:
    enabled: true
    format: json

globalArguments:
  - "--global.sendanonymoususage=false"
  - "--entrypoints.websecure.http.tls.options=default@file"
  - "--providers.file.filename=/data/dynamic_conf.yml"
  - "--ping.entrypoint=traefik"

nodeSelector:
  node-role.kubernetes.io/worker: "true"

tolerations:
  - key: "node-role.kubernetes.io/master"
    operator: "Exists"
    effect: "NoSchedule"

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
              - key: app.kubernetes.io/name
                operator: In
                values:
                  - traefik
          topologyKey: kubernetes.io/hostname