Add production-ready Traefik configuration with secure headers, TLS settings, and rate limiting

This commit is contained in:
Jeppe Bundgaard
2026-02-16 11:39:28 +01:00
parent 21f64bbb5f
commit a709656ba3
3 changed files with 86 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
services:
traefik:
# Use hardened Traefik config in production (no staging CA, no tracing/metrics)
volumes:
- ./services/traefik/traefik.prod.yml:/etc/traefik/traefik.yml:ro
- ./services/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro
- ./services/traefik/acme.json:/acme.json
ports:
- "80:80"
- "443:443"
# Remove public exposure of internal datastores in production
db:
ports: []
redis:
ports: []
## Usage (examples):
## - With explicit files (recommended):
## docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d traefik caddy php1 php2 php3 php4 php5 db redis
##
## - Or set COMPOSE_FILE for the shell session (PowerShell on Windows):
## $env:COMPOSE_FILE = "docker-compose.yml;docker-compose.prod.yml"
## docker compose up -d traefik caddy php1 php2 php3 php4 php5 db redis
##
## Notes:
## - Traefik uses Lets Encrypt production. Ensure DNS A/AAAA records for api.truckwash.dk and traefik.truckwash.dk point to this host and ports 80/443 are reachable.
## - The dashboard is protected by basic auth and an IP allowlist (defined in dynamic.yml). Replace the bcrypt hash before enabling in production.
+29
View File
@@ -33,9 +33,38 @@ http:
- 10.0.0.0/8 - 10.0.0.0/8
- 172.16.0.0/12 - 172.16.0.0/12
- 192.168.0.0/16 - 192.168.0.0/16
secure-headers:
headers:
sslRedirect: true
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: false
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: "strict-origin-when-cross-origin"
customFrameOptionsValue: "SAMEORIGIN"
permissionsPolicy: "geolocation=(), microphone=(), camera=(), payment=()"
addVaryHeader: true
api-ratelimit:
rateLimit:
average: 100
burst: 200
services: services:
cloud-svc: cloud-svc:
loadBalancer: loadBalancer:
servers: servers:
- url: "http://94.130.142.41:11000" - url: "http://94.130.142.41:11000"
tls:
options:
default:
minVersion: VersionTLS12
sniStrict: true
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
+28
View File
@@ -0,0 +1,28 @@
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
docker:
exposedByDefault: false
file:
filename: /etc/traefik/dynamic.yml
watch: true
api:
dashboard: true
log:
level: WARN
accessLog: {}
certificatesResolvers:
le:
acme:
email: jb@truckwash.dk
storage: /acme.json
httpChallenge:
entryPoint: web