Skip to content

Traefik Reverse Proxy Documentation

Table of Contents

  1. Overview
  2. Why Traefik?
  3. Architecture & Configuration
  4. SSL Certificate Management
  5. Authentication Integration
  6. Routing Patterns
  7. Key Configuration Files
  8. Common Operations
  9. Integration with Services
  10. Security Considerations
  11. Troubleshooting
  12. Future Improvements

Overview

Traefik serves as the primary reverse proxy and ingress controller for all services in this infrastructure. It sits at the edge of our Docker network, handling:

  • SSL/TLS termination for all HTTPS traffic
  • Automatic certificate management via Let's Encrypt and Cloudflare DNS
  • Dynamic service discovery through Docker labels
  • Request routing based on hostnames and URL paths
  • Load balancing across service replicas
  • Middleware application (authentication, redirects, path stripping)

All external traffic flows through Traefik before reaching backend services, providing a single point of control for security, routing, and certificate management.

Why Traefik?

The Decision Matrix

When selecting a reverse proxy solution, several factors influenced the choice of Traefik:

1. Native Docker Integration

Unlike traditional reverse proxies (Nginx, Apache), Traefik was built with containers in mind. It automatically discovers services through Docker labels, eliminating the need for manual configuration files and restarts when services change.

2. Dynamic Configuration

Traefik watches the Docker socket for container events. When a new service starts with appropriate labels, Traefik automatically: - Creates routing rules - Provisions SSL certificates - Updates its configuration without downtime

This is crucial for a dynamic environment where services are frequently added, removed, or updated.

3. Automatic SSL with DNS Challenge

Our infrastructure uses Cloudflare for DNS management. Traefik's native support for Cloudflare DNS challenges means: - No need to expose port 80 for HTTP challenges - Works behind firewalls and NAT - Wildcard certificates (*.rbnk.uk) are automatically provisioned - Certificates renew automatically before expiration

4. Unified Configuration Approach

Services define their routing requirements through Docker labels, keeping all configuration in one place (docker-compose.yml). This prevents configuration drift and makes services self-documenting.

5. Production-Ready Features

  • Built-in health checks and circuit breakers
  • Prometheus metrics export capability
  • Access logging with configurable formats
  • WebSocket support out of the box
  • HTTP/2 and HTTP/3 support

Alternative Considered

Nginx Proxy Manager was considered but rejected because: - Required separate UI for configuration - Less dynamic - manual intervention for new services - Additional database dependency - Less flexible middleware system

Architecture & Configuration

Core Components

Internet → Cloudflare DNS → Server (80/443) → Traefik → Docker Services
                                          Docker Socket
                                          (Service Discovery)

Configuration Layers

Traefik uses a three-tier configuration system:

  1. Static Configuration (traefik.yml)
  2. Defines entrypoints (ports)
  3. Sets up providers (Docker, file)
  4. Configures certificate resolvers
  5. Rarely changes after initial setup

  6. Dynamic Configuration (/dynamic/*.yml)

  7. Defines reusable middlewares
  8. Sets up manual routes (if needed)
  9. Can be updated without restart

  10. Service Configuration (Docker labels)

  11. Per-service routing rules
  12. TLS settings
  13. Middleware assignments
  14. Changes with each service deployment

Docker Label System

Services communicate their routing needs through labels. Here's the anatomy of a typical configuration:

labels:
  # Enable Traefik routing for this container
  - traefik.enable=true

  # Specify which Docker network to use (critical for multi-network setups)
  - traefik.docker.network=traefik_proxy

  # Define the routing rule (when to route to this service)
  - traefik.http.routers.myservice.rule=Host(`myservice.rbnk.uk`)

  # Use HTTPS entrypoint
  - traefik.http.routers.myservice.entrypoints=websecure

  # Enable TLS and specify certificate resolver
  - traefik.http.routers.myservice.tls=true
  - traefik.http.routers.myservice.tls.certresolver=cf

  # Tell Traefik which port the service listens on
  - traefik.http.services.myservice.loadbalancer.server.port=8080

SSL Certificate Management

Cloudflare DNS Challenge

The infrastructure uses DNS challenges for certificate validation because:

  1. No Port Requirements: Works without exposing port 80
  2. Wildcard Support: Can issue *.rbnk.uk certificates
  3. Security: No need for temporary web server exposure
  4. Automation: Cloudflare API enables fully automated renewal

Certificate Storage

Certificates are stored in /srv/dockerdata/traefik/letsencrypt/acme.json with strict permissions (600). This file contains: - Private keys - Certificate chains - ACME account information - Renewal metadata

Important: Always backup acme.json before Traefik updates or migrations.

Certificate Lifecycle

  1. Initial Request: When a new Host rule is detected, Traefik checks if a certificate exists
  2. Validation: Traefik creates a TXT record via Cloudflare API
  3. Issuance: Let's Encrypt validates the DNS record and issues the certificate
  4. Storage: Certificate is stored in acme.json
  5. Renewal: Traefik automatically renews certificates 30 days before expiration

Authentication Integration

Traefik integrates with Authentik to provide OAuth2/OIDC authentication for web services while maintaining API accessibility. The implementation uses a dual-route strategy that differentiates between browser and API access patterns.

Key Features

  • Centralized Authentication: Single sign-on across all protected services
  • Dual-Route Strategy: Browser access protected, API access unprotected
  • Priority-Based Routing: Higher priority routes for API endpoints
  • Forward Authentication: Authentik validates requests and provides user context

Quick Reference

For services requiring both browser and API access:

labels:
  # Browser access (protected)
  - "traefik.http.routers.service.middlewares=authentik-secured@file"
  # API access (unprotected, higher priority)
  - "traefik.http.routers.service-api.rule=Host(`service.rbnk.uk`) && PathPrefix(`/api/`)"
  - "traefik.http.routers.service-api.priority=100"
  - "traefik.http.routers.service-api.middlewares=api-access@file"

Detailed Documentation

Routing Patterns

Host-Based Routing

Most services use subdomain-based routing:

traefik.http.routers.service.rule=Host(`service.rbnk.uk`)

This is preferred because: - Clean URLs for each service - Easy to remember - No path conflicts between services - Allows services to use root path

Path-Based Routing

Used when multiple services share a domain (like Supabase components):

# Route /auth/v1/* to auth service
traefik.http.routers.auth.rule=Host(`supabase.rbnk.uk`) && PathPrefix(`/auth/v1`)

# Strip the prefix before forwarding
traefik.http.middlewares.auth-strip.stripprefix.prefixes=/auth/v1

Priority and Specificity

Traefik evaluates rules by specificity. More specific rules take precedence:

  1. Host() && PathPrefix() - Most specific
  2. Host() && Path() - Exact path match
  3. Host() - Domain only (catch-all for that domain)

This is why Supabase Studio (with only Host()) serves as the catch-all after specific API paths are matched.

Middleware Chains

Middlewares modify requests/responses. They're applied in order:

# Multiple middlewares applied left-to-right
traefik.http.routers.storage.middlewares=supa-storage-health@file,supa-storage-strip

In this example: 1. supa-storage-health rewrites /health to /status 2. supa-storage-strip removes the /storage/v1 prefix

Key Configuration Files

/srv/dockerdata/traefik/docker-compose.yml

Primary service definition. Key sections:

  • Command flags: Define core behavior (providers, entrypoints, resolver)
  • Environment: Cloudflare credentials for DNS challenges
  • Volumes:
  • Docker socket (read-only) for service discovery
  • Configuration files
  • Certificate storage
  • Labels: Self-configuration for Traefik dashboard

/srv/dockerdata/traefik/traefik.yml

Static configuration. Defines:

  • Entrypoints: Port 80 (HTTP) and 443 (HTTPS)
  • Providers: Docker and file providers enabled
  • Certificate resolver: Cloudflare DNS challenge settings
  • API/Dashboard: Enabled for monitoring

/srv/dockerdata/traefik/dynamic/middlewares.yml

Reusable middleware definitions:

  • redirect-to-https: Forces HTTPS for all services
  • traefik-dashboard-auth: Basic auth for Traefik UI
  • supa-storage-health: Custom path rewrite for Supabase storage

/srv/dockerdata/traefik/.env

Environment variables:

CF_API_TOKEN=<cloudflare-api-token>
CF_DNS_API_TOKEN=<cloudflare-dns-token>
ACME_EMAIL=<email-for-lets-encrypt>

Common Operations

View Active Routes

# List all active HTTP routers
docker exec traefik wget -qO- http://localhost:8080/api/http/routers | jq

# List all services
docker exec traefik wget -qO- http://localhost:8080/api/http/services | jq

# Check specific router details
docker exec traefik wget -qO- http://localhost:8080/api/http/routers/supa-studio@docker | jq

Certificate Management

# View certificate details
docker exec traefik cat /letsencrypt/acme.json | jq '.cf.Certificates[] | {domains: .domain.main, expires: .certificate | @base64d | split("\n")[0]}'

# Force certificate renewal (delete and restart)
docker compose -f /srv/dockerdata/traefik/docker-compose.yml down
rm /srv/dockerdata/traefik/letsencrypt/acme.json
docker compose -f /srv/dockerdata/traefik/docker-compose.yml up -d

Debug Routing Issues

# Enable debug logging
sed -i 's/level: INFO/level: DEBUG/' /srv/dockerdata/traefik/traefik.yml
docker compose -f /srv/dockerdata/traefik/docker-compose.yml restart

# Watch logs for routing decisions
docker logs -f traefik 2>&1 | grep -E "(router|service|middleware)"

# Test routing without SSL
curl -H "Host: myservice.rbnk.uk" http://localhost:80

Add New Service

  1. Ensure service is on traefik_proxy network:

    networks:
      - traefik_proxy
    

  2. Add required labels:

    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik_proxy
      - traefik.http.routers.myapp.rule=Host(`myapp.rbnk.uk`)
      - traefik.http.routers.myapp.entrypoints=websecure
      - traefik.http.routers.myapp.tls.certresolver=cf
      - traefik.http.services.myapp.loadbalancer.server.port=3000
    

  3. Start service and verify:

    docker compose up -d
    docker logs traefik | grep myapp
    

Integration with Services

Network Architecture

Services must join the traefik_proxy network to be discoverable:

networks:
  traefik_proxy:
    external: true  # Network created separately

This separation ensures: - Only exposed services join the proxy network - Internal services remain isolated - Clear security boundaries

Service Patterns

Simple Web Service

# Basic HTTPS service with automatic certificates
labels:
  - traefik.enable=true
  - traefik.http.routers.app.rule=Host(`app.rbnk.uk`)
  - traefik.http.routers.app.entrypoints=websecure
  - traefik.http.routers.app.tls.certresolver=cf
  - traefik.http.services.app.loadbalancer.server.port=3000

API with Path Routing

# API service with path prefix and stripping
labels:
  - traefik.enable=true
  - traefik.http.routers.api.rule=Host(`main.rbnk.uk`) && PathPrefix(`/api/v1`)
  - traefik.http.routers.api.middlewares=api-strip
  - traefik.http.middlewares.api-strip.stripprefix.prefixes=/api/v1

Protected Service

# Service with authentication middleware
labels:
  - traefik.enable=true
  - traefik.http.routers.admin.rule=Host(`admin.rbnk.uk`)
  - traefik.http.routers.admin.middlewares=admin-auth@file

Multi-Service Applications

Supabase demonstrates advanced integration with multiple services under one domain:

  1. API Services (/auth/v1, /rest/v1, /storage/v1): Path-based routing with prefix stripping
  2. Studio UI: Catch-all router for remaining paths
  3. HTTP→HTTPS Redirect: Dedicated router for protocol upgrade

This pattern allows complex applications to present a unified interface while maintaining service separation.

Security Considerations

Network Isolation

  • Read-only Docker socket: Traefik can discover but not modify containers
  • External network separation: Only public services join traefik_proxy
  • No exposed ports: Services don't bind to host ports directly

Certificate Security

  • Strict file permissions: acme.json is 600 (owner-only access)
  • Automated renewal: Reduces risk of expired certificates
  • DNS validation: No temporary web server exposure

Access Control

  • Basic Auth: Available for simple protection (Traefik dashboard)
  • Middleware chains: Can add multiple authentication layers
  • Service-level security: Each service can implement additional auth

Headers and Security Policies

Security headers are automatically applied to all HTTPS traffic via the security-headers middleware configured on the websecure entrypoint:

http:
  middlewares:
    security-headers:
      headers:
        stsSeconds: 31536000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        contentTypeNosniff: true
        browserXssFilter: true
        referrerPolicy: "strict-origin-when-cross-origin"
        permissionsPolicy: "camera=(), microphone=(), geolocation=()"
        customFrameOptionsValue: "SAMEORIGIN"

These headers provide: - HSTS: Forces HTTPS connections for 1 year - Content-Type Options: Prevents MIME type sniffing attacks - XSS Protection: Browser-level XSS filtering - Frame Options: Prevents clickjacking attacks - Permissions Policy: Restricts browser feature access

Cloudflare SSL/TLS Requirements

For proper SSL operation with Chrome and other browsers:

  1. Set SSL/TLS mode to "Full (strict)" in Cloudflare dashboard
  2. Enable "Always Use HTTPS" to force secure connections
  3. Configure HSTS in Cloudflare Edge Certificates

See SSL Troubleshooting Guide for diagnosing certificate warnings.

Rate Limiting

Protect services from abuse:

http:
  middlewares:
    rate-limit:
      rateLimit:
        average: 100  # requests per second
        burst: 200    # burst capacity

Troubleshooting

Common Issues and Solutions

1. "404 Page Not Found"

Cause: No router matches the request Debug:

# Check if router exists
docker exec traefik wget -qO- http://localhost:8080/api/http/routers | jq .[].rule

# Verify service has correct labels
docker inspect <container> | jq '.[0].Config.Labels' | grep traefik

2. "502 Bad Gateway"

Cause: Traefik cannot reach the service Debug:

# Check if service is on correct network
docker inspect <container> | jq '.[0].NetworkSettings.Networks' | grep traefik_proxy

# Verify port is correct
docker exec <container> netstat -tlnp

# Test connectivity from Traefik
docker exec traefik wget -qO- http://<service>:<port>

3. Certificate Errors

Cause: DNS challenge failed or rate limited Debug:

# Check Traefik logs for ACME errors
docker logs traefik 2>&1 | grep -i "acme\|certificate"

# Verify Cloudflare credentials
docker exec traefik env | grep CF_

# Check rate limits
curl https://crt.sh/?q=rbnk.uk | grep "Let's Encrypt"

4. Service Not Updating

Cause: Label changes not detected Debug:

# Force router refresh
docker compose restart <service>

# Check if old router still exists
docker exec traefik wget -qO- http://localhost:8080/api/http/routers | jq 'keys'

5. Middleware Not Applied

Cause: Incorrect middleware reference or order Debug:

# List all middlewares
docker exec traefik wget -qO- http://localhost:8080/api/http/middlewares | jq

# Check middleware assignment
docker exec traefik wget -qO- http://localhost:8080/api/http/routers/<router>@docker | jq .middlewares

Debug Mode

Enable verbose logging when troubleshooting:

# Temporarily enable debug logs
docker exec traefik sh -c 'echo "log:" > /tmp/debug.yml && echo "  level: DEBUG" >> /tmp/debug.yml'
docker compose -f /srv/dockerdata/traefik/docker-compose.yml restart

# Watch specific components
docker logs -f traefik 2>&1 | grep -i "<component>"

Health Checks

# Traefik health endpoint
curl -f http://localhost:8080/ping

# Dashboard accessibility
curl -f https://traefik.rbnk.uk/api/overview

# Certificate status
docker exec traefik sh -c 'ls -la /letsencrypt/acme.json'

Future Improvements

Planned Enhancements

  1. Observability Stack
  2. Prometheus metrics export
  3. Grafana dashboards for traffic analysis
  4. Access log aggregation with Loki
  5. Distributed tracing with Jaeger

  6. Advanced Security

  7. Web Application Firewall (WAF) rules
  8. Geographic IP filtering
  9. DDoS protection with rate limiting
  10. OAuth2/OIDC proxy integration

  11. Performance Optimization

  12. HTTP/3 (QUIC) support
  13. Cache middleware for static assets
  14. Compression middleware
  15. Connection pooling optimization

  16. High Availability

  17. Redis backend for distributed configuration
  18. Multiple Traefik instances with shared state
  19. Automated failover
  20. Zero-downtime updates

  21. Developer Experience

  22. Automated DNS record creation
  23. Service catalog with templates
  24. Self-service portal for routing rules
  25. Integration with CI/CD pipelines

Configuration as Code

Future migration to GitOps workflow:

# Future: Kubernetes-style CRDs for Traefik
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: myservice
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`myservice.rbnk.uk`)
      kind: Rule
      services:
        - name: myservice
          port: 80

Monitoring and Alerting

Proposed monitoring stack: - Uptime monitoring: External health checks - Certificate expiry alerts: 7-day warning threshold - Traffic anomaly detection: Baseline and alert on deviations - Performance metrics: Response time percentiles

Disaster Recovery

Enhanced backup strategy: - Automated acme.json backups to object storage - Configuration version control - Rapid restoration procedures - Certificate backup to secure vault


Summary

Traefik provides a robust, Docker-native reverse proxy solution that automates certificate management, service discovery, and request routing. Its label-based configuration keeps infrastructure as code principles intact while providing the flexibility needed for complex routing scenarios.

The choice of Traefik over traditional reverse proxies was driven by its cloud-native design, automatic configuration updates, and excellent Docker integration. Combined with Cloudflare DNS challenges, it provides a secure, automated edge layer for all services in the infrastructure.

For questions or issues not covered in this documentation, check the Traefik logs first (docker logs traefik), then consult the official Traefik documentation at https://doc.traefik.io/.