Files
headquarter/docs/deployment/traefik.md
Fusion 83f94b1f09 docs: comprehensive documentation overhaul
Add complete documentation structure:
- Frontend architecture documentation
- Database schema documentation
- Deployment guides (Docker, Traefik, Authentik, Environment)
- Development guides (Setup, Testing, Contributing, Quality Gates)
- Deployment architecture documentation
- Updated docs README with complete navigation

All new features and APIs are now documented.
Quality gates: docs only, no code changes
2026-05-19 14:18:20 +02:00

7.2 KiB

Traefik Reverse Proxy Setup

Overview

Traefik serves as the reverse proxy and load balancer for Headquarter in production, handling:

  • SSL/TLS termination
  • Automatic HTTPS via Let's Encrypt
  • Route-based traffic distribution
  • WebSocket support

Architecture

Internet
    ↓
Traefik (443)
    ├───▶ api.yourdomain.com → Headquarter API (8000)
    └───▶ app.yourdomain.com → Headquarter Web (80)

Prerequisites

  • Docker Compose installed
  • DNS records pointing to your server:
    • api.yourdomain.com → Server IP
    • app.yourdomain.com → Server IP
  • Ports 80 and 443 open in firewall

Configuration

1. Environment Variables

# .env file
API_DOMAIN=api.headquarter.example.com
WEB_DOMAIN=app.headquarter.example.com

# Traefik network (shared with other Traefik instances)
TRAEFIK_NETWORK=web

# SSL Certificate resolver
TRAEFIK_CERT_RESOLVER=letsencrypt

2. Traefik Labels

Services are configured via Docker labels:

# API Service labels
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.headquarter-api.rule=Host(`api.headquarter.example.com`)"
  - "traefik.http.routers.headquarter-api.entrypoints=websecure"
  - "traefik.http.routers.headquarter-api.tls=true"
  - "traefik.http.routers.headquarter-api.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
  - "traefik.http.services.headquarter-api.loadbalancer.server.port=8000"

# Web Service labels
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.headquarter-frontend.rule=Host(`app.headquarter.example.com`)"
  - "traefik.http.routers.headquarter-frontend.entrypoints=websecure"
  - "traefik.http.routers.headquarter-frontend.tls=true"
  - "traefik.http.routers.headquarter-frontend.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
  - "traefik.http.services.headquarter-frontend.loadbalancer.server.port=80"

3. External Network

Connect to existing Traefik instance:

networks:
  traefik:
    external: true
    name: ${TRAEFIK_NETWORK:-traefik}

Deployment Steps

Step 1: Verify DNS

Ensure DNS records resolve to your server:

nslookup api.headquarter.example.com
nslookup app.headquarter.example.com

Step 2: Start Services

# Start with Traefik compose file
docker compose -f docker-compose.traefik.yml up -d

# Verify containers are running
docker compose -f docker-compose.traefik.yml ps

Step 3: Check SSL Certificates

# View Traefik logs
docker compose -f docker-compose.traefik.yml logs -f

# Check certificate status
curl -v https://api.headquarter.example.com/health

Step 4: Run Migrations

docker compose -f docker-compose.traefik.yml exec api alembic upgrade head

SSL Configuration

Let's Encrypt (Default)

Automatic certificate generation and renewal:

labels:
  - "traefik.http.routers.headquarter-api.tls.certresolver=letsencrypt"

Custom Certificates

For custom or wildcard certificates:

labels:
  - "traefik.http.routers.headquarter-api.tls=true"
  - "traefik.http.routers.headquarter-api.tls.certresolver=myresolver"

Self-Signed (Development)

labels:
  - "traefik.http.routers.headquarter-api.tls=true"
  - "traefik.http.routers.headquarter-api.tls.certresolver=selfsigned"

Advanced Configuration

Rate Limiting

labels:
  - "traefik.http.middlewares.ratelimit.ratelimit.average=100"
  - "traefik.http.routers.headquarter-api.middlewares=ratelimit"

Basic Auth (for staging)

labels:
  - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
  - "traefik.http.routers.headquarter-api.middlewares=auth"

CORS Headers

labels:
  - "traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=*"
  - "traefik.http.routers.headquarter-api.middlewares=cors"

Troubleshooting

Certificate Issues

Problem: Certificate not generated

# Check Traefik logs
docker compose logs traefik

# Verify DNS resolution
nslookup your-domain.com

# Check port 80 is accessible (required for HTTP challenge)
curl -I http://your-domain.com

Problem: Certificate expired

# Force renewal
docker compose restart traefik

# Or delete acme.json and restart
rm acme.json
docker compose restart traefik

Routing Issues

Problem: 404 errors

# Check Traefik dashboard (if enabled)
# http://traefik.yourdomain.com

# Verify labels are correct
docker compose -f docker-compose.traefik.yml config

# Check container is on correct network
docker network inspect ${TRAEFIK_NETWORK:-traefik}

Problem: Services not detected

# Verify traefik.enable label
docker compose -f docker-compose.traefik.yml exec api labels

# Check Docker provider in Traefik
docker compose logs traefik | grep "Provider connection established"

Maintenance

Update Traefik

# Pull latest Traefik image
docker compose -f docker-compose.traefik.yml pull traefik

# Restart
docker compose -f docker-compose.traefik.yml up -d traefik

View Dashboard

Enable Traefik dashboard (secure it in production):

# traefik.yml
dashboard:
  enabled: true

# Add to docker-compose.traefik.yml
labels:
  - "traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)"
  - "traefik.http.routers.dashboard.tls=true"
  - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"

Security Considerations

  1. Always use HTTPS in production (redirect HTTP to HTTPS)
  2. Secure Traefik dashboard with authentication
  3. Use strong certificate resolver (Let's Encrypt production)
  4. Keep Traefik updated for security patches
  5. Restrict Docker socket access if using Docker provider

Example Complete Configuration

# docker-compose.traefik.yml
services:
  api:
    build:
      context: ./apps/api
    environment:
      API_DOMAIN: ${API_DOMAIN}
      WEB_DOMAIN: ${WEB_DOMAIN}
      # ... other env vars
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.headquarter-api.rule=Host(`${API_DOMAIN}`)"
      - "traefik.http.routers.headquarter-api.entrypoints=websecure"
      - "traefik.http.routers.headquarter-api.tls=true"
      - "traefik.http.routers.headquarter-api.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
      - "traefik.http.services.headquarter-api.loadbalancer.server.port=8000"
    networks:
      - backend
      - traefik

  web:
    build:
      context: ./apps/web
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.headquarter-frontend.rule=Host(`${WEB_DOMAIN}`)"
      - "traefik.http.routers.headquarter-frontend.entrypoints=websecure"
      - "traefik.http.routers.headquarter-frontend.tls=true"
      - "traefik.http.routers.headquarter-frontend.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-letsencrypt}"
      - "traefik.http.services.headquarter-frontend.loadbalancer.server.port=80"
    networks:
      - traefik

networks:
  traefik:
    external: true
    name: ${TRAEFIK_NETWORK:-traefik}
  backend:
    internal: true

Resources