Claude
Skills
Sign in
Back

traefik

Included with Lifetime
$97 forever

Traefik v3 cloud-native reverse proxy. Covers providers, entrypoints, routers, middlewares, services, Docker labels, TLS/ACME, dashboard, and metrics. USE WHEN: user mentions "traefik", "traefik v3", "traefik docker", "traefik labels", "traefik middleware", "traefik dashboard", "traefik tls", "traefik acme", "traefik router", "traefik entrypoint", "traefik reverse proxy", "traefik cloudflare", "traefik let's encrypt", "traefik rate limit" DO NOT USE FOR: Caddy-based setups - use `caddy` skill, Nginx load balancing - use `load-balancer` skill, Kubernetes ingress with nginx-ingress - use `kubernetes` skill, Application-level TLS inside app code

Cloud & DevOps

What this skill does

# Traefik v3 Core Knowledge

## Core Concepts

```
┌─────────────────────────────────────────────────────────────────┐
│  PROVIDERS          ENTRYPOINTS        ROUTERS         SERVICES │
│  ──────────         ───────────        ───────         ──────── │
│  Docker labels  →   :80  (web)    →   Host rule   →   LB pool  │
│  File provider  →   :443 (websecure)  PathPrefix       backend  │
│  Kubernetes     →   :8080 (dashboard) Headers          servers  │
└─────────────────────────────────────────────────────────────────┘
```

- **Provider**: Where Traefik reads configuration (Docker, file, Kubernetes, Consul…)
- **Entrypoint**: Network port + protocol that Traefik listens on
- **Router**: Matches requests by rule (Host, PathPrefix, Header) → sends to a service
- **Middleware**: Transforms requests/responses between router and service
- **Service**: The upstream backend (load balancer with one or more servers)

---

## Static Config — `traefik.yml`

Static config defines infrastructure-level settings. Requires restart to change.

```yaml
# /etc/traefik/traefik.yml  (or mounted at /traefik.yml in Docker)

# Global settings
global:
  checkNewVersion: false
  sendAnonymousUsage: false

# API & dashboard
api:
  dashboard: true
  insecure: false        # NEVER true in production

# Entrypoints
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"
    http:
      tls:
        certResolver: letsencrypt
      middlewares:
        - security-headers@file    # Apply to all HTTPS routes
  metrics:
    address: ":8082"

# Certificate resolvers
certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: /letsencrypt/acme.json        # Persistent volume required
      # HTTP challenge (default) — requires port 80 open
      httpChallenge:
        entryPoint: web

  letsencrypt-dns:
    acme:
      email: [email protected]
      storage: /letsencrypt/acme-dns.json
      dnsChallenge:
        provider: cloudflare                  # Set CF_DNS_API_TOKEN env var
        delayBeforeCheck: 30                  # Wait for DNS propagation

# Providers
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false                   # IMPORTANT: require explicit opt-in
    network: traefik-public                   # Default network for container comms
  file:
    directory: /etc/traefik/dynamic/          # Watch for changes automatically
    watch: true

# Logging
log:
  level: INFO                                 # DEBUG | INFO | WARN | ERROR
  filePath: /var/log/traefik/traefik.log

# Access logs
accessLog:
  filePath: /var/log/traefik/access.log
  bufferingSize: 100
  fields:
    headers:
      defaultMode: drop
      names:
        User-Agent: keep
        X-Forwarded-For: keep

# Metrics
metrics:
  prometheus:
    entryPoint: metrics
    addServicesLabels: true
    addRoutersLabels: true
```

---

## Docker Compose — Full Example

```yaml
# docker-compose.yml
version: "3.9"

services:
  traefik:
    image: traefik:v3.3
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/traefik/traefik.yml:/traefik.yml:ro
      - /etc/traefik/dynamic/:/etc/traefik/dynamic/:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik-letsencrypt:/letsencrypt
    environment:
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      # Dashboard router
      - "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.service=api@internal"
      - "traefik.http.routers.dashboard.middlewares=dashboard-auth"
      # Dashboard basic auth: echo $(htpasswd -nbB admin 'password') | sed -e s/\\$/\\$\\$/g
      - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$10$$hash..."

  # Example application
  api:
    image: myapp/api:1.4.2
    restart: unless-stopped
    networks:
      - traefik-public
      - internal
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.example.com`)"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.routers.api.middlewares=rate-limit,security-headers"
      # Service port (required when container exposes multiple ports)
      - "traefik.http.services.api.loadbalancer.server.port=3000"
      # Health check
      - "traefik.http.services.api.loadbalancer.healthcheck.path=/health"
      - "traefik.http.services.api.loadbalancer.healthcheck.interval=10s"
      - "traefik.http.services.api.loadbalancer.healthcheck.timeout=3s"

  # Frontend app with path-based routing
  frontend:
    image: myapp/frontend:2.1.0
    restart: unless-stopped
    networks:
      - traefik-public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`example.com`) || Host(`www.example.com`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
      - "traefik.http.routers.frontend.middlewares=www-redirect,security-headers"
      - "traefik.http.services.frontend.loadbalancer.server.port=80"

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    networks:
      - internal                        # Not on traefik-public — no external routing
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=${DB_PASSWORD}

networks:
  traefik-public:
    external: true                      # Pre-created: docker network create traefik-public
  internal:
    driver: bridge

volumes:
  traefik-letsencrypt:
  postgres-data:
```

---

## Dynamic Config — File Provider

```yaml
# /etc/traefik/dynamic/middlewares.yml
http:
  middlewares:
    # HTTP → HTTPS redirect (also configured at entrypoint level above)
    redirect-to-https:
      redirectScheme:
        scheme: https
        permanent: true

    # HSTS + security headers
    security-headers:
      headers:
        stsSeconds: 31536000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        contentTypeNosniff: true
        browserXssFilter: true
        referrerPolicy: "strict-origin-when-cross-origin"
        frameDeny: true
        customResponseHeaders:
          X-Powered-By: ""
          Server: ""

    # Rate limiting
    rate-limit:
      rateLimit:
        average: 100          # Requests per second (average)
        burst: 50             # Burst allowance
        period: 1m            # Window period

    # Strip /api prefix before forwarding
    strip-api-prefix:
      stripPrefix:
        prefixes:
          - "/api"

    # Add /v1 prefix
    add-v1-prefix:
      addPrefix:
        prefix: "/v1"

    # Basic auth
    internal-auth:
      basicAuth:
        usersFile: /etc/traefik/users.htpasswd
        removeHeader: true    # Strip Authorization before passing to upstream

    # IP whitelist (Traefik v3: use ipAllowList)
    office-only:
      ipAllowList:
        sourceRange:
          - "10.0.0.0/8"
          - "203.0.113.42/32"

    # Retry on failure
    retry-middleware:
      retry:
        attempts: 3
        initialInterval: 100ms

    # www redirect
    www-redirect:
      redirectRegex:
        regex: "^https?://www\\.example\\.com/(.*)"
        replacement: "https://example.com/${1}"
        permanent: true

    # Circuit breaker
    circuit-breaker:
      circuitBreaker:
        expression: "ResponseCodeRatio(500, 600, 0, 

Related in Cloud & DevOps