# 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

```bash
# .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:

```yaml
# 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:

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

## Deployment Steps

### Step 1: Verify DNS

Ensure DNS records resolve to your server:

```bash
nslookup api.headquarter.example.com
nslookup app.headquarter.example.com
```

### Step 2: Start Services

```bash
# 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

```bash
# 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

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

## SSL Configuration

### Let's Encrypt (Default)

Automatic certificate generation and renewal:

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

### Custom Certificates

For custom or wildcard certificates:

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

### Self-Signed (Development)

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

## Advanced Configuration

### Rate Limiting

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

### Basic Auth (for staging)

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

### CORS Headers

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

## Troubleshooting

### Certificate Issues

**Problem**: Certificate not generated
```bash
# 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
```bash
# Force renewal
docker compose restart traefik

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

### Routing Issues

**Problem**: 404 errors
```bash
# 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
```bash
# 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

```bash
# 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):

```yaml
# 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

```yaml
# 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

- [Traefik Documentation](https://doc.traefik.io/traefik/)
- [Docker Compose Integration](https://doc.traefik.io/traefik/providers/docker/)
- [Let's Encrypt Configuration](https://doc.traefik.io/traefik/https/acme/)
