1. Ne rien exposer par défaut #
Sécuriser Traefik lui-même.
Checklist #
Provider et dashboard #
# traefik.yml
providers:
docker:
endpoint: tcp://socket-proxy:2375 # via un proxy de socket en lecture seule
exposedByDefault: false # un service n'est publié que s'il porte traefik.enable=true
network: proxy
api:
dashboard: true
insecure: false # jamais d'API non authentifiée sur le port 8080# docker-socket-proxy : seuls les appels nécessaires sont autorisés
socket-proxy:
image: tecnativa/docker-socket-proxy
environment: { CONTAINERS: 1, NETWORKS: 1, SERVICES: 1, TASKS: 0, POST: 0 }
volumes: ["/var/run/docker.sock:/var/run/docker.sock:ro"]
networks: [proxy]# Protéger le dashboard : mot de passe haché (bcrypt), $ doublés dans les labels Compose
htpasswd -nbB admin 'MotDePasseFort' | sed -e 's/\$/\$\$/g'Erreur Courante : N'exposez jamais le port8080(API/dashboard) sur Internet, et ne montez pasdocker.socken écriture dans Traefik.
2. TLS et en-têtes de sécurité #
HTTPS partout, configuration moderne.
Options TLS et middlewares #
# dynamic/tls.yml
tls:
options:
default:
minVersion: VersionTLS12
sniStrict: true
http:
middlewares:
securite:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
contentTypeNosniff: true
frameDeny: true
referrerPolicy: strict-origin-when-cross-origin
limite:
rateLimit: { average: 100, period: 1s, burst: 50 }
compression:
compress: {}
chaine-standard:
chain: { middlewares: [securite, limite, compression] }curl -sI https://app.exemple.fr | grep -i -E "strict-transport|server|x-frame"
nmap --script ssl-enum-ciphers -p 443 app.exemple.fr
docker run --rm -ti drwetter/testssl.sh app.exemple.fr3. Disponibilité #
Plusieurs instances et certificats.
Haute disponibilité #
- Déployez au moins deux instances derrière un load balancer ou une IP virtuelle.
- Le stockage ACME local (
acme.json) ne se partage pas : en HA, utilisez cert-manager (Kubernetes), Traefik Enterprise ou des certificats fournis par fichier. - Activez les health checks sur les services et réglez les timeouts.
http:
services:
api:
loadBalancer:
healthCheck: { path: /health, interval: 10s, timeout: 2s }
servers: [{ url: "http://10.0.0.11:8080" }, { url: "http://10.0.0.12:8080" }]
entryPoints:
websecure:
address: ":443"
transport:
respondingTimeouts: { readTimeout: 60s, writeTimeout: 60s, idleTimeout: 180s }
lifeCycle: { graceTimeOut: 30s }4. Observabilité #
Voir ce qui se passe.
Logs, métriques et traces #
accessLog:
format: json
filters: { statusCodes: ["400-599"] }
log: { level: INFO, format: json }
metrics:
prometheus: { addRoutersLabels: true, addServicesLabels: true }
tracing:
otlp: { grpc: { endpoint: "alloy:4317", insecure: true } }# PromQL utiles
sum by (service) (rate(traefik_service_requests_total{code=~"5.."}[5m]))
histogram_quantile(0.95, sum by (le, service) (rate(traefik_service_request_duration_seconds_bucket[5m])))
traefik healthcheck --ping # sonde de santé (ping: {} dans la configuration)Bonne Pratique : Gardez les fichiers dynamiques dans Git et validez la configuration avant déploiement avec un conteneur de test.
Schéma de référence et vérification rapide #
Visualiser le principe et le contrôler en ligne de commande.
Schéma de référence #
curl -sI https://app.exemple.fr | head -8
nc -zv traefik.exemple.fr 8080 # doit échouer depuis Internet