Files
michaelschiemer/deployment/stacks/traefik/README.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

9.8 KiB

Traefik Stack - Reverse Proxy with SSL

Overview

Traefik acts as the central reverse proxy for all services, handling:

  • Automatic SSL certificate generation via Let's Encrypt
  • HTTP to HTTPS redirection
  • Service discovery via Docker labels
  • Security headers and compression
  • Rate limiting and access control

Services

  • traefik.michaelschiemer.de - Traefik Dashboard (BasicAuth protected)
    • Protected by BasicAuth authentication
    • Accessible via HTTPS with Let's Encrypt certificate

Local Development

For local development, use the separate local configuration to avoid port conflicts and Let's Encrypt errors:

Quick Start (Local Development)

# Ensure Docker network exists
docker network create traefik-public 2>/dev/null || true

# Start Traefik with local configuration
cd deployment/stacks/traefik
docker compose -f docker-compose.local.yml up -d

# Check logs
docker compose -f docker-compose.local.yml logs -f

# Access dashboard at http://localhost:8093/dashboard/
# Note: Dashboard is served on the API port (8093) when api.insecure=true

Local Development Configuration

The local configuration (docker-compose.local.yml and traefik.local.yml) differs from production:

  • Bridge network instead of host mode (avoids port conflicts)
  • Port mappings: 8081:80 (HTTP) and 8093:8080 (API/Dashboard)
    • Note: HTTPS not needed locally - avoids port conflicts with web container (8443:443)
  • HTTP-only (no ACME/Let's Encrypt) for local development
  • Dashboard: Accessible at http://localhost:8093/dashboard/ (HTTP, no authentication)
    • Also available: http://localhost:8093/api/rawdata and http://localhost:8093/api/http/routers
    • Note: Dashboard is served on the API port (8093) when api.insecure=true in traefik.local.yml
  • No acme.json required
  • Console logging (human-readable) instead of JSON file logs

Local Development vs Production

Feature Local (docker-compose.local.yml) Production (docker-compose.yml)
Network Mode Bridge Bridge
Ports 8081:80, 8093:8080 (HTTP only) 80:80, 443:443, 2222:2222
SSL/TLS HTTP-only HTTPS with Let's Encrypt
Dashboard http://localhost:8093/dashboard/ https://traefik.michaelschiemer.de
Authentication None (local dev) BasicAuth
Logging Console (human-readable) JSON files
ACME Disabled Enabled

Troubleshooting Local Development

Container restarts in loop:

  • Check if ports 8081 or 8093 are already in use: netstat -tlnp | grep -E ':(8081|8093)' || ss -tlnp | grep -E ':(8081|8093)'
  • Verify Docker network exists: docker network ls | grep traefik-public
  • Check logs: docker compose -f docker-compose.local.yml logs -f traefik

Services not accessible through Traefik:

  • Ensure services are on traefik-public network
  • Verify Traefik labels are correctly configured
  • Check that services are running: docker compose ps

Prerequisites

  1. Docker Network

    docker network create traefik-public
    
  2. ACME Storage File

    touch acme.json
    chmod 600 acme.json
    
  3. DNS Configuration Point these domains to your server IP (94.16.110.151):

    • michaelschiemer.de
    • *.michaelschiemer.de (wildcard)

Configuration

1. Create Environment File

cp .env.example .env

2. Generate Dashboard Password

# Generate password hash
htpasswd -nb admin your_secure_password

# Example output:
# admin:$apr1$8kj9d7lj$r.x5jhLVPLuCDLvJ6x0Hd0

# Important: In docker-compose.yml, replace $ with $$
# admin:$$apr1$$8kj9d7lj$$r.x5jhLVPLuCDLvJ6x0Hd0

Update the traefik.http.middlewares.traefik-auth.basicauth.users label in docker-compose.yml.

3. Adjust Configuration (Optional)

Edit traefik.yml for:

  • Log levels
  • Certificate resolvers
  • Additional entry points
  • Metrics configuration

Deployment

Initial Setup

# Create network
docker network create traefik-public

# Create acme.json
touch acme.json
chmod 600 acme.json

# Create log directories
mkdir -p logs

# Start Traefik
docker compose up -d

Verify Deployment

# Check container status
docker compose ps

# Check logs
docker compose logs -f

# Test dashboard access
curl -I https://traefik.michaelschiemer.de

# Check certificate
openssl s_client -connect traefik.michaelschiemer.de:443 -servername traefik.michaelschiemer.de < /dev/null

Middleware Configuration

Traefik provides several reusable middlewares in dynamic/middlewares.yml:

Security Headers

labels:
  - "traefik.http.routers.myapp.middlewares=security-headers-global@file"

Rate Limiting

labels:
  # Strict: 50 req/s
  - "traefik.http.routers.myapp.middlewares=rate-limit-strict@file"

  # Moderate: 100 req/s
  - "traefik.http.routers.myapp.middlewares=rate-limit-moderate@file"

  # Lenient: 200 req/s
  - "traefik.http.routers.myapp.middlewares=rate-limit-lenient@file"

Compression

labels:
  - "traefik.http.routers.myapp.middlewares=gzip-compression@file"

VPN-Only Access (WireGuard Network)

labels:
  # Restrict access to WireGuard VPN network only (10.8.0.0/24)
  - "traefik.http.routers.myapp.middlewares=vpn-only@file"

  # Combined: VPN-only + BasicAuth (order matters - VPN check first, then BasicAuth)
  - "traefik.http.routers.myapp.middlewares=vpn-only@file,traefik-auth"

Middleware Chains

labels:
  # Default chain: Security + Compression
  - "traefik.http.routers.myapp.middlewares=default-chain@file"

  # Admin chain: Security + Compression + Rate Limiting
  - "traefik.http.routers.myapp.middlewares=admin-chain@file"

Service Integration

Example Service Configuration

Add these labels to any Docker service to expose it through Traefik:

services:
  myapp:
    image: myapp:latest
    networks:
      - traefik-public
    labels:
      # Enable Traefik
      - "traefik.enable=true"

      # Router configuration
      - "traefik.http.routers.myapp.rule=Host(`app.michaelschiemer.de`)"
      - "traefik.http.routers.myapp.entrypoints=websecure"
      - "traefik.http.routers.myapp.tls=true"
      - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"

      # Service configuration
      - "traefik.http.services.myapp.loadbalancer.server.port=80"

      # Middleware (optional)
      - "traefik.http.routers.myapp.middlewares=default-chain@file"

networks:
  traefik-public:
    external: true

Monitoring

Dashboard Access

Access the Traefik dashboard at: https://traefik.michaelschiemer.de

Default credentials (change in production):

  • Username: admin
  • Password: (set via htpasswd)

Logs

# Access logs (HTTP requests)
tail -f logs/access.log

# Traefik logs (errors, warnings)
tail -f logs/traefik.log

# Container logs
docker compose logs -f traefik

Prometheus Metrics

Traefik exposes Prometheus metrics for monitoring:

# Add to Prometheus scrape config
- job_name: 'traefik'
  static_configs:
    - targets: ['traefik:8082']

Troubleshooting

Certificate Issues

# Check acme.json permissions
ls -la acme.json
# Should be: -rw------- (600)

# View certificate status
docker compose logs traefik | grep -i "certificate"

# Force certificate renewal
rm acme.json
touch acme.json
chmod 600 acme.json
docker compose restart

DNS Issues

# Verify DNS resolution
dig michaelschiemer.de
dig git.michaelschiemer.de

# Check from external
nslookup michaelschiemer.de 8.8.8.8

Service Not Accessible

# Check Traefik can reach service
docker network inspect traefik-public

# Verify service labels
docker inspect <container_name> | grep -A 20 Labels

# Check Traefik logs for routing errors
docker compose logs traefik | grep -i error

Port Conflicts

# Check if ports 80/443 are free
sudo netstat -tlnp | grep -E ':80|:443'

# Stop conflicting services
sudo systemctl stop nginx  # or apache2

Security Hardening

1. IP Whitelisting

Uncomment and configure in dynamic/middlewares.yml:

admin-whitelist:
  ipWhiteList:
    sourceRange:
      - "your.vpn.ip.range/32"
      - "10.0.0.0/8"

2. Strong Dashboard Password

# Generate strong password
openssl rand -base64 32

# Create hash
htpasswd -nb admin "your_strong_password"

3. Rate Limiting

Apply rate limiting to sensitive endpoints:

labels:
  - "traefik.http.routers.admin.middlewares=rate-limit-strict@file"

4. DDoS Protection

# In traefik.yml - add entry point middleware
entryPoints:
  websecure:
    address: ":443"
    http:
      middlewares:
        - rate-limit-moderate@file

Backup

Important Files

  • acme.json - SSL certificates
  • traefik.yml - Static configuration
  • dynamic/ - Dynamic configuration
# Backup certificates
cp acme.json acme.json.backup.$(date +%Y%m%d)

# Backup configuration
tar -czf traefik-config-backup.tar.gz traefik.yml dynamic/

Updates

# Pull latest image
docker compose pull

# Restart with new image
docker compose up -d

# Verify
docker compose ps
docker compose logs -f

Performance Tuning

Connection Limits

In traefik.yml:

entryPoints:
  websecure:
    transport:
      respondingTimeouts:
        readTimeout: 60s
        writeTimeout: 60s
      lifeCycle:
        requestAcceptGraceTimeout: 0s
        graceTimeOut: 10s

Resource Limits

In docker-compose.yml:

deploy:
  resources:
    limits:
      memory: 512M
      cpus: '0.5'
    reservations:
      memory: 256M
      cpus: '0.25'

Support

For issues with Traefik configuration:

  1. Check official Traefik documentation: https://doc.traefik.io/traefik/
  2. Review logs: docker compose logs -f
  3. Verify network connectivity: docker network inspect traefik-public