# 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 (VPN-only + BasicAuth protected)
  - ?? **Nur ?ber WireGuard VPN erreichbar** (10.8.0.0/24)
  - Zus?tzlich durch BasicAuth gesch?tzt
  - ?ffentlicher Zugriff ist blockiert

## Local Development

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

### Quick Start (Local Development)

```bash
# 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:8080/dashboard/
```

### 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**: `8080:80` only (HTTP-only for local development)
   - 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:8080/dashboard/` (HTTP, no authentication)
   - Also available: `http://localhost:8080/api/rawdata` and `http://localhost:8080/api/http/routers`
- **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 | Host |
| Ports | 8080:80 (HTTP only) | Direct binding (80, 443) |
| SSL/TLS | HTTP-only | HTTPS with Let's Encrypt |
| Dashboard | `http://localhost:8080/dashboard/` | `https://traefik.michaelschiemer.de` |
| Authentication | None (local dev) | VPN + BasicAuth |
| Logging | Console (human-readable) | JSON files |
| ACME | Disabled | Enabled |

### Troubleshooting Local Development

**Container restarts in loop:**
- Check if port 8080 is already in use: `netstat -tlnp | grep ':8080' || ss -tlnp | grep ':8080'`
- 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**
   ```bash
   docker network create traefik-public
   ```

2. **ACME Storage File**
   ```bash
   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

```bash
cp .env.example .env
```

### 2. Generate Dashboard Password

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

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

```bash
# 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
```yaml
labels:
  - "traefik.http.routers.myapp.middlewares=security-headers-global@file"
```

### Rate Limiting
```yaml
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
```yaml
labels:
  - "traefik.http.routers.myapp.middlewares=gzip-compression@file"
```

### VPN-Only Access (WireGuard Network)
```yaml
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
```yaml
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:

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

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

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

## Troubleshooting

### Certificate Issues

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

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

# Check from external
nslookup michaelschiemer.de 8.8.8.8
```

### Service Not Accessible

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

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

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

### 2. Strong Dashboard Password

```bash
# Generate strong password
openssl rand -base64 32

# Create hash
htpasswd -nb admin "your_strong_password"
```

### 3. Rate Limiting

Apply rate limiting to sensitive endpoints:

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

### 4. DDoS Protection

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

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

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

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

### Resource Limits

In `docker-compose.yml`:

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