Professional Traefik v3.6 reverse proxy setup for multi-server Docker deployments with automatic SSL certificate management via Let's Encrypt.
- âś… Automatic HTTPS with Let's Encrypt
- âś… HTTP to HTTPS redirect
- âś… Secure dashboard with authentication
- âś… Docker integration for automatic service discovery
- âś… Security headers and rate limiting
- âś… Structured logging
- âś… Support for multiple servers
- âś… Wildcard certificate support (via DNS challenge)
- âś… Environment-based configuration
traefik/
├── docker-compose.yml # Main Docker Compose configuration
├── traefik.yml # Traefik static configuration
├── acme.json # SSL certificates storage (auto-generated)
├── .env # Environment variables (create from .env.example)
├── .env.example # Environment variables template
├── .gitignore # Git ignore rules
├── deploy.sh # Deployment automation script
├── config/
│ └── middlewares.yml # Dynamic middleware configuration
├── examples/
│ └── example-service.yml # Service configuration examples
├── logs/ # Traefik logs (auto-generated)
└── README.md # This file
- Docker and Docker Compose installed
- Domain name(s) pointing to your server(s)
- Ports 80 and 443 available
- (Optional) DNS provider API credentials for wildcard certificates
# Create the external Docker network
docker network create traefik_proxy
# Create acme.json with correct permissions
touch acme.json
chmod 600 acme.json
# Create logs directory
mkdir -p logs
# Copy environment template
cp .env.example .envEdit .env file with your settings:
# Dashboard domain
TRAEFIK_DASHBOARD_DOMAIN=traefik.yourdomain.com
# Generate dashboard password (requires apache2-utils)
# On macOS: brew install httpd
# On Ubuntu: sudo apt-get install apache2-utils
echo $(htpasswd -nb admin yourpassword) | sed -e s/\\$/\\$\\$/g
# Paste the output in .env as TRAEFIK_DASHBOARD_AUTH valueEdit traefik.yml and update:
- Email address in
certificatesResolvers.letsencrypt.acme.email - Domain names in
entryPoints.websecure.http.tls.domains
Option A: Using the deployment script
./deploy.sh deploy
# Or for interactive menu:
./deploy.shOption B: Manual deployment
# Start Traefik
docker compose up -d
# Check logs
docker compose logs -f
# Verify status
docker compose psVisit https://traefik.yourdomain.com (or your configured domain) and log in with your credentials.
To route traffic to your containerized applications, add them to the traefik_proxy network and configure labels:
version: '3.8'
services:
webapp:
image: your-app:latest
networks:
- traefik_proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.webapp.rule=Host(`app.yourdomain.com`)"
- "traefik.http.routers.webapp.entrypoints=websecure"
- "traefik.http.routers.webapp.tls=true"
- "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
- "traefik.http.services.webapp.loadbalancer.server.port=8080"
networks:
traefik_proxy:
external: truelabels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`app1.com`) || Host(`app2.com`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls=true"
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt"labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`yourdomain.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls=true"
- "traefik.http.routers.api.middlewares=api-stripprefix"
- "traefik.http.middlewares.api-stripprefix.stripprefix.prefixes=/api"labels:
- "traefik.enable=true"
- "traefik.http.routers.secure-app.rule=Host(`secure.yourdomain.com`)"
- "traefik.http.routers.secure-app.entrypoints=websecure"
- "traefik.http.routers.secure-app.tls=true"
- "traefik.http.routers.secure-app.middlewares=security-headers@file,rate-limit@file"See examples/example-service.yml for more configuration examples.
To deploy across multiple servers:
# On each server
git clone <repository-url> /opt/traefik
cd /opt/traefikEach server gets its own .env configuration:
# Server 1 - Main
TRAEFIK_DASHBOARD_DOMAIN=traefik-1.yourdomain.com
# Server 2 - Secondary
TRAEFIK_DASHBOARD_DOMAIN=traefik-2.yourdomain.com
# Server 3 - Tertiary
TRAEFIK_DASHBOARD_DOMAIN=traefik-3.yourdomain.com# On each server
./deploy.sh deployPoint your domains to the appropriate servers:
- Use A records for specific servers
- Use load balancers for high availability
- Consider GeoDNS for regional routing
Simple setup, works out of the box:
- Requires ports 80 and 443 open
- One certificate per domain
- Configured by default in
traefik.yml
For wildcard certificates (*.yourdomain.com):
- Uncomment DNS challenge section in
traefik.yml:
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 30
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"-
Add DNS provider credentials to
.env -
Update domain configuration for wildcard
Supported DNS Providers:
- Cloudflare, AWS Route53, Google Cloud DNS
- DigitalOcean, Namecheap, OVH
- Full list
For testing, use Let's Encrypt staging:
# In your service labels
- "traefik.http.routers.myapp.tls.certresolver=letsencrypt-staging"Generate secure passwords:
# Generate new password
htpasswd -nb admin newpassword | sed -e s/\\$/\\$\\$/g
# Or use the deployment script
./deploy.sh passwordUncomment and configure in config/middlewares.yml:
ip-whitelist:
ipWhiteList:
sourceRange:
- "YOUR.IP.ADDRESS/32"
- "10.0.0.0/8"Apply to services:
labels:
- "traefik.http.routers.myapp.middlewares=ip-whitelist@file"Pre-configured in config/middlewares.yml:
- HSTS with preload
- XSS protection
- Content type sniffing prevention
- Frame denial
- Custom security headers
# All logs
docker compose logs -f
# Access logs
tail -f logs/access.log
# Error logs
tail -f logs/traefik.log
# Using deployment script
./deploy.sh logsUncomment Prometheus metrics in traefik.yml and add:
entryPoints:
metrics:
address: ":8082"# Check acme.json
cat acme.json | jq
# Reset certificates
docker compose down
rm acme.json
touch acme.json && chmod 600 acme.json
docker compose up -d- Verify DNS points to server
- Check firewall allows ports 80, 443, 8080
- Verify
TRAEFIK_DASHBOARD_DOMAINin.env - Check authentication string format
# Check if service is detected
docker compose exec traefik traefik healthcheck
# Verify network
docker network inspect traefik_proxy
# Check labels
docker inspect <container_name>chmod 600 acme.json
chown $USER:$USER acme.json# Pull latest image
docker compose pull
# Restart with new image
docker compose up -d
# Or use deployment script
./deploy.sh restart
# Check version
docker compose exec traefik traefik version# Backup certificates and config
tar -czf traefik-backup-$(date +%Y%m%d).tar.gz \
acme.json .env traefik.yml config/# Extract backup
tar -xzf traefik-backup-YYYYMMDD.tar.gz
# Set permissions
chmod 600 acme.json
# Restart
docker compose up -dThe deploy.sh script provides an easy way to manage your Traefik deployment:
# Interactive menu
./deploy.sh
# Direct commands
./deploy.sh deploy # Full deployment
./deploy.sh setup # Setup only
./deploy.sh start # Start Traefik
./deploy.sh stop # Stop Traefik
./deploy.sh restart # Restart Traefik
./deploy.sh logs # View logs
./deploy.sh password # Generate password
./deploy.sh status # Check status
./deploy.sh --help # Show helpCreate config/errors.yml:
http:
middlewares:
error-pages:
errors:
status:
- "400-599"
service: error-service
query: /{status}.html
services:
error-service:
loadBalancer:
servers:
- url: http://error-pages-container/Add to traefik.yml:
entryPoints:
postgres:
address: ":5432"Configure service:
labels:
- "traefik.tcp.routers.postgres.rule=HostSNI(`*`)"
- "traefik.tcp.routers.postgres.entrypoints=postgres"
- "traefik.tcp.services.postgres.loadbalancer.server.port=5432"This setup uses Traefik v3.6, which includes:
- Improved performance and stability
- Enhanced middleware options
- Better WebAssembly plugin support
- Updated configuration syntax
For migration from v2.x, see the Traefik v3 Migration Guide.
This configuration is provided as-is for use in your projects.
For issues specific to this setup, check:
- Logs:
docker compose logs -f - Dashboard:
https://your-dashboard-domain/dashboard/ - Traefik docs: https://doc.traefik.io/