Traefik Reverse Proxy Documentation¶
Table of Contents¶
- Overview
- Why Traefik?
- Architecture & Configuration
- SSL Certificate Management
- Authentication Integration
- Routing Patterns
- Key Configuration Files
- Common Operations
- Integration with Services
- Security Considerations
- Troubleshooting
- 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:
- Static Configuration (
traefik.yml) - Defines entrypoints (ports)
- Sets up providers (Docker, file)
- Configures certificate resolvers
-
Rarely changes after initial setup
-
Dynamic Configuration (
/dynamic/*.yml) - Defines reusable middlewares
- Sets up manual routes (if needed)
-
Can be updated without restart
-
Service Configuration (Docker labels)
- Per-service routing rules
- TLS settings
- Middleware assignments
- 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:
- No Port Requirements: Works without exposing port 80
- Wildcard Support: Can issue
*.rbnk.ukcertificates - Security: No need for temporary web server exposure
- 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¶
- Initial Request: When a new Host rule is detected, Traefik checks if a certificate exists
- Validation: Traefik creates a TXT record via Cloudflare API
- Issuance: Let's Encrypt validates the DNS record and issues the certificate
- Storage: Certificate is stored in
acme.json - 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¶
- Authentication Middleware - Complete middleware configuration guide
- Authentication Strategy - Implementation patterns and best practices
- Authentik Service - Authentik setup and configuration
Routing Patterns¶
Host-Based Routing¶
Most services use subdomain-based routing:
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:
Host() && PathPrefix()- Most specificHost() && Path()- Exact path matchHost()- 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¶
-
Ensure service is on
traefik_proxynetwork: -
Add required labels:
-
Start service and verify:
Integration with Services¶
Network Architecture¶
Services must join the traefik_proxy network to be discoverable:
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:
- API Services (
/auth/v1,/rest/v1,/storage/v1): Path-based routing with prefix stripping - Studio UI: Catch-all router for remaining paths
- 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.jsonis 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:
- Set SSL/TLS mode to "Full (strict)" in Cloudflare dashboard
- Enable "Always Use HTTPS" to force secure connections
- 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¶
- Observability Stack
- Prometheus metrics export
- Grafana dashboards for traffic analysis
- Access log aggregation with Loki
-
Distributed tracing with Jaeger
-
Advanced Security
- Web Application Firewall (WAF) rules
- Geographic IP filtering
- DDoS protection with rate limiting
-
OAuth2/OIDC proxy integration
-
Performance Optimization
- HTTP/3 (QUIC) support
- Cache middleware for static assets
- Compression middleware
-
Connection pooling optimization
-
High Availability
- Redis backend for distributed configuration
- Multiple Traefik instances with shared state
- Automated failover
-
Zero-downtime updates
-
Developer Experience
- Automated DNS record creation
- Service catalog with templates
- Self-service portal for routing rules
- 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/.