Files
docker-compose/proxy/compose.yaml
Sebastian Krüger b420f1d4bf feat: add comprehensive Traefik security hardening
Added security enhancements to Traefik reverse proxy:

**TLS Security:**
- Minimum TLS 1.2 enforced
- Strong cipher suites (ECDHE, AES-GCM, ChaCha20)
- Modern curve preferences (P-521, P-384)
- SNI strict mode enabled

**HTTP Security Headers:**
- HSTS with 1-year max-age, includeSubdomains, and preload
- X-Frame-Options: SAMEORIGIN (clickjacking protection)
- X-XSS-Protection enabled
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy (disable camera, mic, geolocation, etc.)
- X-Robots-Tag for SEO control

**Rate Limiting Middlewares:**
- General: 100 req/s average, 50 burst
- API endpoints: 30 req/s average, 15 burst

**Configuration:**
- Enabled Traefik file provider for dynamic config
- Security headers applied globally to web-secure entrypoint
- Dynamic config in proxy/dynamic/security.yaml
- Auto-reloads on config changes

All HTTPS traffic now benefits from enhanced security headers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 23:20:34 +01:00

67 lines
2.0 KiB
YAML

services:
traefik:
image: ${PROXY_DOCKER_IMAGE}
container_name: ${PROXY_COMPOSE_PROJECT_NAME}_app
restart: unless-stopped
command:
# API & Dashboard
- '--api.dashboard=false'
- '--api.insecure=false'
# Logging
- '--log.level=${PROXY_LOG_LEVEL:-INFO}'
- '--accesslog=true'
# Global
- '--global.sendAnonymousUsage=false'
- '--global.checkNewVersion=true'
# Docker Provider
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=false'
- '--providers.docker.network=${NETWORK_NAME}'
# File Provider for dynamic configuration
- '--providers.file.directory=/etc/traefik/dynamic'
- '--providers.file.watch=true'
# Entrypoints
- '--entrypoints.web.address=:${PROXY_PORT_HTTP:-80}'
- '--entrypoints.web-secure.address=:${PROXY_PORT_HTTPS:-443}'
# Global HTTP to HTTPS redirect
- '--entrypoints.web.http.redirections.entryPoint.to=web-secure'
- '--entrypoints.web.http.redirections.entryPoint.scheme=https'
- '--entrypoints.web.http.redirections.entryPoint.permanent=true'
# TLS Security Options
- '--entrypoints.web-secure.http.tls.options=default@file'
- '--entrypoints.web-secure.http.middlewares=security-headers@file'
# Let's Encrypt
- '--certificatesresolvers.resolver.acme.tlschallenge=true'
- '--certificatesresolvers.resolver.acme.email=${ADMIN_EMAIL}'
- '--certificatesresolvers.resolver.acme.storage=/letsencrypt/acme.json'
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
networks:
- compose_network
ports:
- "${PROXY_PORT_HTTP:-80}:80"
- "${PROXY_PORT_HTTPS:-443}:443"
volumes:
- letsencrypt_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./dynamic:/etc/traefik/dynamic:ro
volumes:
letsencrypt_data:
name: ${PROXY_COMPOSE_PROJECT_NAME}_letsencrypt_data