Welcome to Part 4! So far we've covered the fundamentals (Part 1), setup (Part 2), and basic deployments (Part 3). Now we're going to level up with production-grade features.
What We'll Cover
- Rate Limiting - Protect against abuse and DDoS
- Authentication Middleware - Add login to any service
- Custom Headers - Security headers, CORS, etc.
- WebSocket Support - Real-time applications
- IP Whitelisting - Restrict access by IP
- Redirects and Rewrites - URL manipulation
- Multiple Ports - Expose multiple services from one container
- Custom Error Pages - Brand your error responses
Time estimate: 2-3 hours
Understanding Middleware
Before diving into specific features, let's understand middleware - Traefik's most powerful concept.
What is Middleware?
Middleware sits between the internet and your application, processing requests:
Internet → Traefik → [Middleware 1] → [Middleware 2] → Your App
Common middleware uses:
- Add authentication before reaching app
- Limit request rate
- Add/modify HTTP headers
- Redirect URLs
- Compress responses
Middleware Syntax
Middleware is defined in Docker labels:
labels:
# Define middleware
- "traefik.http.middlewares.{name}.{type}.{config}=value"
# Apply middleware to router
- "traefik.http.routers.{router-name}.middlewares={middleware-name}"
You can chain multiple middleware:
- "traefik.http.routers.myapp.middlewares=auth,ratelimit,compress"
They execute in order: auth → ratelimit → compress
Feature 1: Rate Limiting
Rate limiting prevents abuse by restricting request frequency.
Basic Rate Limiting
Limit requests per IP address:
services:
myapp:
# ... existing config ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.example.com`)"
# Define rate limit middleware
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
# Apply middleware
- "traefik.http.routers.myapp.middlewares=ratelimit"
Parameters explained:
average=100: Allow 100 requests per second averageburst=50: Allow bursts up to 50 above average
When to use: Public APIs, login pages, any endpoint prone to abuse
Advanced Rate Limiting
Different limits for different endpoints:
labels:
# API has strict limits
- "traefik.http.middlewares.api-limit.ratelimit.average=10"
- "traefik.http.middlewares.api-limit.ratelimit.period=1m"
# Frontend has looser limits
- "traefik.http.middlewares.web-limit.ratelimit.average=100"
- "traefik.http.middlewares.web-limit.ratelimit.burst=200"
# Apply based on path
- "traefik.http.routers.api.rule=Host(`example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.middlewares=api-limit"
- "traefik.http.routers.web.rule=Host(`example.com`)"
- "traefik.http.routers.web.middlewares=web-limit"
Rate Limit Response Headers
Track limits with headers:
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
# Add headers showing remaining quota
- "traefik.http.middlewares.ratelimit.ratelimit.sourcecriterion.requestheadername=X-Real-IP"
Clients can check X-RateLimit-Limit and X-RateLimit-Remaining headers.
Feature 2: Authentication
Add authentication to ANY service, even if the app doesn't support it natively.
Basic Authentication
Protect an admin panel or private service:
# Generate password hash
apt install -y apache2-utils
htpasswd -nb admin secretpassword
# Output:
# admin:$apr1$xyz$abc123...
Add to docker-compose.yml:
services:
admin-panel:
# ... config ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.admin.rule=Host(`admin.example.com`)"
# Define auth middleware (remember to escape $ as $$)
- "traefik.http.middlewares.admin-auth.basicauth.users=admin:$$apr1$$xyz$$abc123..."
# Apply auth
- "traefik.http.routers.admin.middlewares=admin-auth"
Security note: Always use HTTPS (entrypoints=websecure) with authentication!
Multiple Users
Add multiple users (separated by commas):
labels:
# User 1 and User 2
- "traefik.http.middlewares.auth.basicauth.users=user1:$$apr1$$...,user2:$$apr1$$..."
Forward Authentication (OAuth/SSO)
For advanced auth (Google, GitHub, etc.), use ForwardAuth middleware:
labels:
# Forward to auth service
- "traefik.http.middlewares.oauth.forwardauth.address=http://oauth-provider:4181"
- "traefik.http.middlewares.oauth.forwardauth.authResponseHeaders=X-Forwarded-User"
- "traefik.http.routers.myapp.middlewares=oauth"
Popular auth providers:
- Authelia - Full-featured auth server
- OAuth2 Proxy - Google/GitHub OAuth
- Keycloak - Enterprise SSO
Feature 3: Custom Headers
Add security headers or configure CORS.
Security Headers
Harden your application:
labels:
# Define security headers middleware
- "traefik.http.middlewares.security.headers.framedeny=true"
- "traefik.http.middlewares.security.headers.sslredirect=true"
- "traefik.http.middlewares.security.headers.stsSeconds=315360000"
- "traefik.http.middlewares.security.headers.stsIncludeSubdomains=true"
- "traefik.http.middlewares.security.headers.stsPreload=true"
- "traefik.http.middlewares.security.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.security.headers.browserXssFilter=true"
- "traefik.http.middlewares.security.headers.customFrameOptionsValue=SAMEORIGIN"
# Apply to router
- "traefik.http.routers.myapp.middlewares=security"
Headers explained:
framedeny: Prevent clickjackingsslredirect: Force HTTPSstsSeconds: HSTS max-age (10 years)contentTypeNosniff: Prevent MIME sniffingbrowserXssFilter: Enable XSS filter
CORS Configuration
Allow cross-origin requests for APIs:
labels:
# CORS middleware
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowmethods=GET,POST,PUT,DELETE,OPTIONS"
- "traefik.http.middlewares.api-cors.headers.accesscontrolalloworiginlist=https://app.example.com,https://admin.example.com"
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowheaders=Content-Type,Authorization,X-Requested-With"
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowcredentials=true"
- "traefik.http.middlewares.api-cors.headers.accesscontrolmaxage=100"
# Apply to API router
- "traefik.http.routers.api.middlewares=api-cors"
Important: Be specific with accesscontrolalloworiginlist. Don't use * in production!
Custom Request Headers
Add headers to requests sent to your app:
labels:
# Add custom headers
- "traefik.http.middlewares.custom.headers.customrequestheaders.X-Custom-Header=MyValue"
- "traefik.http.middlewares.custom.headers.customrequestheaders.X-Forwarded-Proto=https"
Your app receives these headers with every request.
Feature 4: WebSocket Support
WebSockets need special handling for real-time apps (chat, live updates, etc.).
Basic WebSocket Configuration
services:
chat-app:
# ... config ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.chat.rule=Host(`chat.example.com`)"
- "traefik.http.services.chat.loadbalancer.server.port=3000"
# WebSocket support (usually works by default, but these ensure it)
- "traefik.http.middlewares.ws-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.ws-headers.headers.customrequestheaders.X-Forwarded-For="
- "traefik.http.routers.chat.middlewares=ws-headers"
Socket.IO Configuration
Socket.IO requires sticky sessions:
labels:
# Enable sticky sessions
- "traefik.http.services.socketio.loadbalancer.sticky.cookie=true"
- "traefik.http.services.socketio.loadbalancer.sticky.cookie.name=io"
- "traefik.http.services.socketio.loadbalancer.sticky.cookie.secure=true"
- "traefik.http.services.socketio.loadbalancer.sticky.cookie.httpOnly=true"
WebSocket Health Checks
Ensure WebSocket endpoints are healthy:
services:
websocket-app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
Feature 5: IP Whitelisting
Restrict access to specific IP addresses.
Basic IP Whitelist
Allow only specific IPs:
labels:
# Define IP whitelist middleware
- "traefik.http.middlewares.admin-whitelist.ipwhitelist.sourcerange=192.168.1.0/24,203.0.113.45/32"
# Apply to admin panel
- "traefik.http.routers.admin.middlewares=admin-whitelist"
IP formats:
- Single IP:
203.0.113.45/32 - Subnet:
192.168.1.0/24(192.168.1.0 - 192.168.1.255) - Multiple: Comma-separated
Combining IP Whitelist with Auth
Extra security for critical services:
labels:
- "traefik.http.middlewares.admin-whitelist.ipwhitelist.sourcerange=203.0.113.0/24"
- "traefik.http.middlewares.admin-auth.basicauth.users=admin:$$apr1$$..."
# Both must pass
- "traefik.http.routers.admin.middlewares=admin-whitelist,admin-auth"
Dynamic IP Lists (Advanced)
For frequently changing IPs, use a file-based provider instead of labels.
Feature 6: Redirects and Rewrites
Manipulate URLs before they reach your app.
Simple Redirect
Redirect old URLs to new ones:
labels:
# Permanent redirect
- "traefik.http.middlewares.redirect-old.redirectregex.regex=^https://old.example.com/(.*)"
- "traefik.http.middlewares.redirect-old.redirectregex.replacement=https://new.example.com/$${1}"
- "traefik.http.middlewares.redirect-old.redirectregex.permanent=true"
- "traefik.http.routers.old-site.rule=Host(`old.example.com`)"
- "traefik.http.routers.old-site.middlewares=redirect-old"
Add Path Prefix
Add prefix before forwarding to app:
labels:
# Add /api prefix
- "traefik.http.middlewares.add-api.addprefix.prefix=/api"
# Request to /users → forwarded to app as /api/users
- "traefik.http.routers.backend.middlewares=add-api"
Strip Path Prefix
Remove prefix before forwarding:
labels:
# Remove /api prefix
- "traefik.http.middlewares.strip-api.stripprefix.prefixes=/api"
# Request to /api/users → forwarded to app as /users
- "traefik.http.routers.api.middlewares=strip-api"
WWW Redirect
Enforce www or non-www:
labels:
# Redirect www to non-www
- "traefik.http.middlewares.nowww.redirectregex.regex=^https://www\\.(.+)"
- "traefik.http.middlewares.nowww.redirectregex.replacement=https://$${1}"
- "traefik.http.middlewares.nowww.redirectregex.permanent=true"
- "traefik.http.routers.www.rule=Host(`www.example.com`)"
- "traefik.http.routers.www.middlewares=nowww"
Feature 7: Multiple Services from One Container
Expose different ports from the same container.
Example: App + Metrics
services:
app:
# ... config ...
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-network"
# Main app on port 3000
- "traefik.http.routers.app-web.rule=Host(`app.example.com`)"
- "traefik.http.routers.app-web.service=app-web-service"
- "traefik.http.services.app-web-service.loadbalancer.server.port=3000"
# Metrics endpoint on port 9090
- "traefik.http.routers.app-metrics.rule=Host(`metrics.example.com`)"
- "traefik.http.routers.app-metrics.service=app-metrics-service"
- "traefik.http.services.app-metrics-service.loadbalancer.server.port=9090"
# Protect metrics with auth
- "traefik.http.middlewares.metrics-auth.basicauth.users=admin:$$apr1$$..."
- "traefik.http.routers.app-metrics.middlewares=metrics-auth"
Key points:
- Each router needs its own service definition
- Explicitly name services to avoid conflicts
- Can apply different middleware to each
Feature 8: Response Compression
Reduce bandwidth and improve load times.
labels:
# Enable compression
- "traefik.http.middlewares.compress.compress=true"
# Optional: specify mime types
- "traefik.http.middlewares.compress.compress.excludedcontenttypes=image/png,image/jpeg"
# Apply to router
- "traefik.http.routers.myapp.middlewares=compress"
Traefik automatically compresses responses with gzip.
Feature 9: Custom Error Pages
Brand your error responses.
Create Error Page Service
services:
error-pages:
image: guillaumebriday/traefik-custom-error-pages
container_name: error-pages
networks:
- traefik-network
labels:
- "traefik.enable=true"
- "traefik.http.services.error-pages.loadbalancer.server.port=80"
# Define error middleware
- "traefik.http.middlewares.errors.errors.status=400-599"
- "traefik.http.middlewares.errors.errors.service=error-pages"
- "traefik.http.middlewares.errors.errors.query=/{status}.html"
Apply to Your Apps
labels:
- "traefik.http.routers.myapp.middlewares=errors"
Now 404, 500, etc. show your branded pages instead of default errors.
Feature 10: Circuit Breaker
Protect backend from cascading failures.
labels:
# Define circuit breaker
- "traefik.http.middlewares.cb.circuitbreaker.expression=NetworkErrorRatio() > 0.3"
# Apply to router
- "traefik.http.routers.api.middlewares=cb"
Expression options:
NetworkErrorRatio() > 0.30: Trips if >30% network errorsResponseCodeRatio(500, 600, 0, 600) > 0.25: Trips if >25% 5xx errorsLatencyAtQuantileMS(50.0) > 100: Trips if median latency >100ms
When tripped, Traefik returns 503 until the backend recovers.
Real-World Example: Production API
Let's combine multiple features:
services:
production-api:
container_name: prod-api
build: ./api
restart: unless-stopped
environment:
- NODE_ENV=production
networks:
- traefik-network
- backend
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-network"
# Routing
- "traefik.http.routers.api.rule=Host(`api.example.com`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
# Rate limiting
- "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.api-ratelimit.ratelimit.burst=50"
# CORS
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowmethods=GET,POST,PUT,DELETE,OPTIONS"
- "traefik.http.middlewares.api-cors.headers.accesscontrolalloworiginlist=https://app.example.com"
- "traefik.http.middlewares.api-cors.headers.accesscontrolallowheaders=Content-Type,Authorization"
# Security headers
- "traefik.http.middlewares.api-security.headers.stsSeconds=315360000"
- "traefik.http.middlewares.api-security.headers.framedeny=true"
- "traefik.http.middlewares.api-security.headers.contentTypeNosniff=true"
# Compression
- "traefik.http.middlewares.api-compress.compress=true"
# Circuit breaker
- "traefik.http.middlewares.api-cb.circuitbreaker.expression=NetworkErrorRatio() > 0.3"
# Apply all middleware
- "traefik.http.routers.api.middlewares=api-ratelimit,api-cors,api-security,api-compress,api-cb"
networks:
traefik-network:
external: true
backend:
driver: bridge
This production-ready API has:
- ✅ Rate limiting (100 req/s)
- ✅ CORS configured
- ✅ Security headers
- ✅ Compression
- ✅ Circuit breaker
- ✅ Automatic HTTPS
Debugging Middleware
Check Applied Middleware
Visit Traefik dashboard → HTTP → Routers → Click your router
You'll see:
- Which middleware are applied
- Order of execution
- Any errors
Test Middleware
# Test rate limit
for i in {1..150}; do curl https://api.example.com; done
# Test CORS
curl -H "Origin: https://app.example.com" -I https://api.example.com/api/data
# Test auth
curl -u admin:password https://admin.example.com
# Test compression
curl -H "Accept-Encoding: gzip" -I https://app.example.com
Common Issues
Middleware not applying:
- Check middleware name matches in router config
- Verify no typos in labels
- Check Traefik logs:
docker logs traefik
Order matters:
# ❌ Wrong: auth runs AFTER ratelimit (waste of resources)
middlewares=ratelimit,auth
# ✅ Right: auth runs FIRST (reject unauthorized early)
middlewares=auth,ratelimit
Performance Considerations
Middleware Overhead
Each middleware adds latency:
- Compression: ~1-5ms
- Auth: ~1-2ms
- Rate limit: <1ms
- Headers: <1ms
Optimize by:
- Only using needed middleware
- Ordering efficiently (auth first, compression last)
- Using caching where possible
Load Testing
Test your setup under load:
# Install Apache Bench
apt install -y apache2-utils
# Test with 1000 requests, 10 concurrent
ab -n 1000 -c 10 https://api.example.com/
# Check results
# Look for: Requests per second, Time per request
Summary
You've learned advanced Traefik features:
- ✅ Rate limiting for protection
- ✅ Authentication middleware
- ✅ Custom headers (security & CORS)
- ✅ WebSocket support
- ✅ IP whitelisting
- ✅ URL redirects and rewrites
- ✅ Multiple services per container
- ✅ Compression for performance
- ✅ Custom error pages
- ✅ Circuit breakers for resilience
What's Next?
In Part 5: Production Best Practices & Troubleshooting, we'll cover:
- Comprehensive troubleshooting guide
- Security hardening checklist
- Monitoring and alerting
- Backup strategies
- High availability
- Migration strategies
- Performance tuning
Continue to Part 5 for production-ready deployment strategies!