
Ce guide vous apprend à configurer les middlewares Traefik en construisant pas à pas un environnement de test. Chaque middleware est présenté avec un cas d’usage, une configuration minimale, et une commande curl pour valider que ça fonctionne.
À la fin, vous saurez :
- Protéger une API avec rate limiting et headers de sécurité
- Sécuriser un backoffice avec authentification et filtrage IP
- Exposer un site public avec compression et protection anti-abus
Public cible : développeurs et ops utilisant Traefik comme reverse proxy.
Prérequis : Docker installé. Ce guide utilise Docker Compose pour le lab.
Accès rapide aux middlewares
Section intitulée « Accès rapide aux middlewares »Vous êtes pressé ? Allez directement au middleware qui vous intéresse :
| Besoin | Middleware | Section |
|---|---|---|
Supprimer /api de l’URL | stripPrefix | Réécriture |
| Ajouter un préfixe | addPrefix | Réécriture |
| Protection par mot de passe | basicAuth | Authentification |
| SSO (Authelia, Keycloak) | forwardAuth | Authentification |
| Limiter les requêtes/seconde | rateLimit | Protection |
| Filtrer par IP | ipAllowList | Protection |
| Limiter requêtes simultanées | inFlightReq | Protection |
| Couper si backend KO | circuitBreaker | Protection |
| Headers de sécurité | headers | Réponse |
| CORS | headers (CORS) | Réponse |
| Compression gzip/brotli | compress | Réponse |
| HTTP → HTTPS | redirectScheme | Redirections |
| Grouper des middlewares | chain | Chaînage |
Recettes prêtes à copier :
- Site public : rate limit + headers + compress
- Backoffice interne : IP filter + SSO + headers
- API publique : rate limit + CORS + headers
Setup du lab (5 min)
Section intitulée « Setup du lab (5 min) »Tout le guide repose sur ce lab. Vous allez créer un environnement Traefik + whoami qui sert de terrain d’expérimentation pour tous les middlewares.
Structure du lab
Section intitulée « Structure du lab »traefik-lab/├── docker-compose.yml├── traefik.yml # Config statique└── config/ └── middlewares.yml # Middlewares (config dynamique)Fichiers à créer
Section intitulée « Fichiers à créer »1. docker-compose.yml
services: traefik: image: traefik:v3.2 ports: - "80:80" - "8080:8080" # Dashboard volumes: - ./traefik.yml:/etc/traefik/traefik.yml:ro - ./config:/etc/traefik/config:ro - /var/run/docker.sock:/var/run/docker.sock:ro labels: - "traefik.enable=true"
# Service de test principal whoami: image: traefik/whoami labels: - "traefik.enable=true" - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)" - "traefik.http.routers.whoami.entrypoints=web"
# API de test (même image, route différente) api: image: traefik/whoami labels: - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`whoami.localhost`) && PathPrefix(`/api`)" - "traefik.http.routers.api.entrypoints=web"2. traefik.yml (config statique)
api: dashboard: true insecure: true # Dashboard sans auth (lab uniquement)
entryPoints: web: address: ":80"
providers: docker: exposedByDefault: false file: directory: /etc/traefik/config watch: true
log: level: INFO3. config/middlewares.yml (vide pour l’instant)
http: middlewares: {}Démarrer le lab
Section intitulée « Démarrer le lab »mkdir -p traefik-lab/configcd traefik-lab# Créer les fichiers ci-dessus, puis :docker compose up -dVérifier que le lab fonctionne
Section intitulée « Vérifier que le lab fonctionne »# Site principalcurl http://whoami.localhost# → Affiche infos whoami (IP, headers...)
# Route APIcurl http://whoami.localhost/api# → Même chose, mais via /api
# Dashboard Traefikopen http://localhost:8080Le lab est prêt. Tous les exemples qui suivent utilisent ce setup.
Glossaire
Section intitulée « Glossaire »| Terme | Définition |
|---|---|
| Middleware | Fonction qui intercepte une requête entre le client et le backend pour la transformer ou la bloquer |
| Chain | Groupe de middlewares exécutés dans l’ordre |
| Router | Règle qui détermine vers quel service envoyer la requête |
| Service | Cible de la requête (backend, load balancer) |
| Entrypoint | Port d’écoute de Traefik (ex: 80, 443) |
| AuthN | Authentification — vérifier l’identité (“qui êtes-vous ?”) |
| AuthZ | Autorisation — vérifier les permissions (“avez-vous le droit ?”) |
| Token bucket | Algorithme de rate limiting : un “seau” se remplit de tokens, chaque requête en consomme un |
| SSE | Server-Sent Events — flux de données en temps réel du serveur vers le client |
| CORS | Cross-Origin Resource Sharing — mécanisme permettant à un site d’accéder à des ressources d’un autre domaine |
Mental model : où s’exécute un middleware ?
Section intitulée « Mental model : où s’exécute un middleware ? »Position dans le flux Traefik
Section intitulée « Position dans le flux Traefik »Un middleware s’exécute après que le routeur a décidé où va la requête, et avant qu’elle n’atteigne le backend. Il peut :
- Bloquer la requête (rate limit, auth, IP filter)
- Transformer la requête (strip prefix, add header)
- Modifier la réponse (headers, compression)
Règle d’or : “Bloquer tôt, transformer tard”
Section intitulée « Règle d’or : “Bloquer tôt, transformer tard” »L’ordre des middlewares est critique. Appliquez cette règle :
Pourquoi ?
- Bloquer tôt économise des ressources : inutile d’authentifier une IP bannie
- Transformer tard garantit que les modifications passent au backend/client
Ordre recommandé
Section intitulée « Ordre recommandé »| Étape | Middlewares | Objectif |
|---|---|---|
| 1 | ipAllowList, rateLimit, inFlightReq | Bloquer les abus |
| 2 | basicAuth, forwardAuth | Vérifier l’identité |
| 3 | stripPrefix, addPrefix, replacePath | Réécrire les chemins |
| 4 | headers (response) | Ajouter headers de sécurité |
| 5 | compress | Compresser la réponse |
Recettes prêtes à l’emploi
Section intitulée « Recettes prêtes à l’emploi »Avant de détailler chaque middleware, voici 3 chains complètes couvrant 90% des cas d’usage. Copiez celle qui correspond à votre besoin.
Recette A — Site public (blog, docs, vitrine)
Section intitulée « Recette A — Site public (blog, docs, vitrine) »Objectif : protection anti-abus + headers de sécurité + compression.
http: middlewares: chain-public-web: chain: middlewares: - rate-limit-web - secure-headers-web - compress-web
rate-limit-web: rateLimit: average: 100 burst: 200
secure-headers-web: headers: frameDeny: true contentTypeNosniff: true stsSeconds: 31536000 stsIncludeSubdomains: true
compress-web: compress: excludedContentTypes: - text/event-streamAppliquer au lab (docker-compose.yml) :
whoami: labels: - "traefik.http.routers.whoami.middlewares=chain-public-web@file"✅ Vérifier :
# Headers de sécurité présentscurl -I http://whoami.localhost# → X-Frame-Options: DENY# → X-Content-Type-Options: nosniff# → Strict-Transport-Security: max-age=31536000
# Compression activecurl -H "Accept-Encoding: gzip" -I http://whoami.localhost# → Content-Encoding: gzipRecette B — Backoffice interne (admin, outils internes)
Section intitulée « Recette B — Backoffice interne (admin, outils internes) »Objectif : accès restreint par IP + authentification SSO.
http: middlewares: chain-internal-app: chain: middlewares: - ip-filter-internal - auth-internal - secure-headers-internal
ip-filter-internal: ipAllowList: sourceRange: - "10.0.0.0/8" - "192.168.0.0/16" - "172.16.0.0/12"
auth-internal: forwardAuth: address: http://authelia:9091/api/verify trustForwardHeader: false authResponseHeaders: - X-Forwarded-User
secure-headers-internal: headers: frameDeny: true contentTypeNosniff: true✅ Vérifier :
# Depuis une IP non autorisée → 403curl http://admin.localhost# → 403 Forbidden
# Depuis une IP autorisée, sans auth → 401 (ou redirect SSO)curl http://admin.localhost# → 401 UnauthorizedRecette C — API publique (REST, GraphQL)
Section intitulée « Recette C — API publique (REST, GraphQL) »Objectif : rate limiting strict + CORS + headers de sécurité.
http: middlewares: chain-api: chain: middlewares: - rate-limit-api - cors-api - secure-headers-api
rate-limit-api: rateLimit: average: 60 burst: 100 period: 1m sourceCriterion: ipStrategy: depth: 1
cors-api: headers: accessControlAllowMethods: - GET - POST - PUT - DELETE - OPTIONS accessControlAllowHeaders: - Authorization - Content-Type accessControlAllowOriginList: - "https://app.example.com" accessControlMaxAge: 86400
secure-headers-api: headers: contentTypeNosniff: true customResponseHeaders: Cache-Control: "no-store"Appliquer au lab :
api: labels: - "traefik.http.routers.api.middlewares=chain-api@file"✅ Vérifier :
# CORS headers présentscurl -I -X OPTIONS http://whoami.localhost/api \ -H "Origin: https://app.example.com" \ -H "Access-Control-Request-Method: POST"# → Access-Control-Allow-Origin: https://app.example.com
# Rate limit (envoyer 200 requêtes)for i in {1..200}; do curl -s -o /dev/null -w "%{http_code}\n" http://whoami.localhost/api; done# → 429 Too Many Requests après dépassementMiddlewares par famille
Section intitulée « Middlewares par famille »Maintenant, détaillons chaque middleware avec une structure répétable :
- 🟢 Quand l’utiliser (+ 2 cas concrets)
- 🔴 Quand ne pas l’utiliser
- Configuration minimale
- ✅ Vérifier (test curl)
- Pièges fréquents
- 🟠 Variante avancée (optionnel)
Famille 1 : Réécriture des chemins
Section intitulée « Famille 1 : Réécriture des chemins »Ces middlewares modifient l’URL avant qu’elle n’atteigne le backend.
StripPrefix — Supprimer un préfixe
Section intitulée « StripPrefix — Supprimer un préfixe »🟢 Quand l’utiliser :
- Vous exposez
/api/usersmais le backend attend/users - Vous avez un préfixe de versioning (
/v1/...) que le backend ne comprend pas
🔴 Quand ne pas l’utiliser :
- Le backend gère déjà le préfixe (framework avec routing)
Configuration minimale :
http: middlewares: strip-api: stripPrefix: prefixes: - /apiAppliquer au lab :
api: labels: - "traefik.http.routers.api.middlewares=strip-api@file"✅ Vérifier :
# Requête vers /api/testcurl http://whoami.localhost/api/test# → Dans la sortie whoami : "GET /test HTTP/1.1"# (le /api a été retiré)Pièges fréquents :
- Le backend renvoie des URLs avec le chemin original (sans
/api) → les liens internes cassent - Oublier que
stripPrefixlaisse un/initial :/api/users→/users(pasusers)
🟠 Variante avancée — StripPrefixRegex :
strip-versions: stripPrefixRegex: regex: - "^/v[0-9]+/"Retire /v1/, /v2/, etc.
AddPrefix — Ajouter un préfixe
Section intitulée « AddPrefix — Ajouter un préfixe »🟢 Quand l’utiliser :
- Le backend attend un préfixe que vous ne voulez pas exposer
- Migration : ancien chemin → nouveau chemin interne
🔴 Quand ne pas l’utiliser :
- Le prefixe est déjà dans l’URL du client
Configuration minimale :
http: middlewares: add-v2: addPrefix: prefix: /v2✅ Vérifier :
curl http://whoami.localhost/users# → Backend reçoit : "GET /v2/users HTTP/1.1"Pièges fréquents :
- Double préfixe si combiné avec stripPrefix dans le mauvais ordre
ReplacePath — Remplacer le chemin entier
Section intitulée « ReplacePath — Remplacer le chemin entier »🟢 Quand l’utiliser :
- Rediriger toutes les requêtes d’une route vers un chemin fixe
- Endpoint de health check unique
🔴 Quand ne pas l’utiliser :
- Vous voulez conserver une partie du chemin original
Configuration minimale :
http: middlewares: health-redirect: replacePath: path: /health✅ Vérifier :
curl http://whoami.localhost/anything# → Backend reçoit : "GET /health HTTP/1.1"Famille 2 : Authentification
Section intitulée « Famille 2 : Authentification »BasicAuth — Authentification simple
Section intitulée « BasicAuth — Authentification simple »🟢 Quand l’utiliser :
- Protection rapide d’un service interne (dev, staging)
- Accès temporaire à un outil sans SSO
🔴 Quand ne pas l’utiliser :
- En production sans HTTPS (credentials en clair !)
- Applications avec beaucoup d’utilisateurs (pas de gestion de sessions)
Configuration minimale :
# Générer le hash (bcrypt recommandé)htpasswd -nbB admin "monsecret"# → admin:$2y$05$...http: middlewares: basic-auth: basicAuth: users: - "admin:$2y$05$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"Appliquer au lab :
whoami: labels: - "traefik.http.routers.whoami.middlewares=basic-auth@file"✅ Vérifier :
# Sans credentials → 401curl http://whoami.localhost# → 401 Unauthorized
# Avec credentials → 200curl -u admin:monsecret http://whoami.localhost# → Réponse whoamiPièges fréquents :
- Hash mal généré (MD5 au lieu de bcrypt) → refusé
- Oublier d’échapper les
$dans Docker labels - Utiliser en production sans HTTPS
🟠 Variante avancée — Fichier htpasswd :
basic-auth-file: basicAuth: usersFile: /etc/traefik/htpasswd removeHeader: true # Ne pas transmettre le header au backendForwardAuth — Déléguer l’authentification
Section intitulée « ForwardAuth — Déléguer l’authentification »🟢 Quand l’utiliser :
- SSO avec Authelia, Keycloak, Authentik
- Authentification centralisée multi-services
🔴 Quand ne pas l’utiliser :
- Service interne simple (préférez BasicAuth)
- Le service auth n’est pas résilient (single point of failure)
Configuration minimale :
http: middlewares: auth-sso: forwardAuth: address: http://authelia:9091/api/verify authResponseHeaders: - X-Forwarded-User - X-Forwarded-Groups✅ Vérifier :
# Sans session → 401 ou 302 (redirect vers login)curl -I http://whoami.localhost# → HTTP/1.1 302 Found# → Location: https://auth.example.com/login?rd=...
# Avec cookie de session valide → 200curl -b "authelia_session=xxx" http://whoami.localhostPièges fréquents :
trustForwardHeader: truesans proxy de confiance → usurpation d’identitéauthResponseHeadersmal configuré → headers sensibles transmis au client (smuggling)- Service auth lent → augmenter les timeouts
🟠 Variante avancée — trustForwardHeader :
auth-behind-proxy: forwardAuth: address: http://authelia:9091/api/verify trustForwardHeader: true # SEULEMENT si derrière un proxy de confiance authResponseHeaders: - X-Forwarded-UserDigestAuth — Authentification digest
Section intitulée « DigestAuth — Authentification digest »🟢 Quand l’utiliser :
- Clients qui ne supportent pas BasicAuth moderne
- Légèrement plus sécurisé que BasicAuth (pas de mot de passe en clair)
🔴 Quand ne pas l’utiliser :
- En production (HTTPS + BasicAuth bcrypt est meilleur)
- Applications modernes (préférez ForwardAuth + SSO)
Configuration minimale :
http: middlewares: digest-auth: digestAuth: users: - "admin:traefik:hash"Voir la documentation officielle pour la génération du hash.
Famille 3 : Protection et résilience
Section intitulée « Famille 3 : Protection et résilience »RateLimit — Limiter les requêtes
Section intitulée « RateLimit — Limiter les requêtes »🟢 Quand l’utiliser :
- Protéger une API contre les abus
- Éviter qu’un client monopolise les ressources
🔴 Quand ne pas l’utiliser :
- Services internes entre microservices (latence ajoutée)
- Quand vous avez un WAF en amont qui fait déjà du rate limiting
Configuration minimale :
http: middlewares: rate-limit: rateLimit: average: 10 # 10 req/s en moyenne burst: 20 # Jusqu'à 20 en rafaleAppliquer au lab :
api: labels: - "traefik.http.routers.api.middlewares=rate-limit@file"✅ Vérifier :
# Envoyer 30 requêtes rapidementfor i in {1..30}; do curl -s -o /dev/null -w "%{http_code} " http://whoami.localhost/apidone# → 200 200 200 ... 429 429 429Pièges fréquents :
sourceCriterion.requestHeaderNameavec un header spoofable (X-Real-IP) → bypass- Oublier que Traefik utilise un token bucket (le burst permet des pics)
- Rate limit trop agressif → faux positifs pour les utilisateurs légitimes
🟠 Variante avancée — Par API key :
rate-limit-by-key: rateLimit: average: 100 burst: 200 period: 1m sourceCriterion: requestHeaderName: X-API-Key # SEULEMENT émis par un service de confianceIPAllowList — Filtrer par IP
Section intitulée « IPAllowList — Filtrer par IP »🟢 Quand l’utiliser :
- Restreindre l’accès à un backoffice par IP
- Whitelister des partenaires ou un VPN
🔴 Quand ne pas l’utiliser :
- IPs dynamiques (FAI résidentiels)
- Alternative à l’authentification (IP != identité)
Configuration minimale :
http: middlewares: ip-whitelist: ipAllowList: sourceRange: - "192.168.1.0/24" - "10.0.0.0/8"✅ Vérifier :
# Depuis une IP autorisée → 200curl http://whoami.localhost
# Depuis une IP non autorisée → 403curl http://whoami.localhost# → 403 ForbiddenPièges fréquents :
- Oublier
ipStrategy.depthderrière un load balancer → bloque le LB, pas le client - Plages CIDR mal calculées
🟠 Variante avancée — Derrière un proxy :
ip-whitelist-behind-lb: ipAllowList: sourceRange: - "192.168.1.0/24" ipStrategy: depth: 1 # Prend l'IP dans X-Forwarded-ForInFlightReq — Limiter les requêtes simultanées
Section intitulée « InFlightReq — Limiter les requêtes simultanées »🟢 Quand l’utiliser :
- Protéger un backend fragile contre la surcharge
- Limiter le nombre de connexions longues (websockets, SSE)
🔴 Quand ne pas l’utiliser :
- APIs stateless rapides (rate limit est plus adapté)
Configuration minimale :
http: middlewares: inflight: inFlightReq: amount: 10 # Max 10 requêtes simultanées par source✅ Vérifier :
# Lancer 20 requêtes lentes en parallèlefor i in {1..20}; do curl -s "http://whoami.localhost/api?delay=5s" &done# → Les 10 premières passent, les suivantes reçoivent 503Pièges fréquents :
- Confondre avec rate limit (qui compte sur le temps, pas les requêtes actives)
sourceCriterionmal configuré → limite globale au lieu de par IP
CircuitBreaker — Couper si backend défaillant
Section intitulée « CircuitBreaker — Couper si backend défaillant »🟢 Quand l’utiliser :
- Protéger les utilisateurs d’un backend instable
- Éviter de saturer un service défaillant avec des retries
🔴 Quand ne pas l’utiliser :
- Backend toujours sain (overhead inutile)
- Quand vous préférez des erreurs explicites (fail fast)
Configuration minimale :
http: middlewares: circuit-breaker: circuitBreaker: expression: "NetworkErrorRatio() > 0.30"Comportement : si plus de 30% des requêtes échouent (erreurs réseau), le circuit s’ouvre et renvoie 503 pendant fallbackDuration (10s par défaut).
✅ Vérifier :
Difficile à tester sans simuler des erreurs backend. En lab, vous pouvez arrêter le service whoami :
docker compose stop whoami# Les requêtes vers whoami déclenchent le circuit après quelques échecsPièges fréquents :
- Expression mal calibrée → circuit s’ouvre trop vite ou jamais
- Oublier
checkPeriodetrecoveryDurationpour le retour à la normale
🟠 Variante avancée — Paramètres de timing :
circuit-breaker-tuned: circuitBreaker: expression: "NetworkErrorRatio() > 0.25 || ResponseCodeRatio(500, 600, 0, 600) > 0.30" checkPeriod: 10s # Fréquence de vérification fallbackDuration: 15s # Durée en mode "ouvert" recoveryDuration: 30s # Durée de récupération progressiveFamille 4 : Réponse (headers, compression)
Section intitulée « Famille 4 : Réponse (headers, compression) »Headers — Ajouter des headers de sécurité
Section intitulée « Headers — Ajouter des headers de sécurité »🟢 Quand l’utiliser :
- Toujours sur les services web (HSTS, X-Frame-Options, CSP)
- Ajouter des headers métier (X-Request-ID, X-API-Version)
🔴 Quand ne pas l’utiliser :
- Le backend gère déjà ces headers (duplication)
Configuration minimale :
http: middlewares: secure-headers: headers: frameDeny: true # X-Frame-Options: DENY contentTypeNosniff: true # X-Content-Type-Options: nosniff browserXssFilter: true # X-XSS-Protection: 1; mode=block stsSeconds: 31536000 # HSTS 1 an stsIncludeSubdomains: trueAppliquer au lab :
whoami: labels: - "traefik.http.routers.whoami.middlewares=secure-headers@file"✅ Vérifier :
curl -I http://whoami.localhost# → X-Frame-Options: DENY# → X-Content-Type-Options: nosniff# → Strict-Transport-Security: max-age=31536000; includeSubDomainsPièges fréquents :
- HSTS sur un site sans HTTPS → les utilisateurs seront bloqués
- CSP trop restrictive → casse le site (tester d’abord en mode report-only)
🟠 Variante avancée — CSP complète :
secure-headers-csp: headers: contentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" customResponseHeaders: X-Robots-Tag: "noindex, nofollow"Headers CORS — Autoriser les requêtes cross-origin
Section intitulée « Headers CORS — Autoriser les requêtes cross-origin »🟢 Quand l’utiliser :
- API consommée par un frontend sur un autre domaine
- Applications SPA (React, Vue, Angular)
🔴 Quand ne pas l’utiliser :
- API interne entre microservices (même origine)
- Quand le framework backend gère déjà CORS
Configuration minimale :
http: middlewares: cors: headers: accessControlAllowMethods: - GET - POST - OPTIONS accessControlAllowOriginList: - "https://app.example.com" accessControlMaxAge: 86400✅ Vérifier :
# Preflight OPTIONScurl -I -X OPTIONS http://whoami.localhost/api \ -H "Origin: https://app.example.com" \ -H "Access-Control-Request-Method: POST"# → Access-Control-Allow-Origin: https://app.example.com# → Access-Control-Allow-Methods: GET, POST, OPTIONSCompress — Compresser les réponses
Section intitulée « Compress — Compresser les réponses »🟢 Quand l’utiliser :
- Sites web avec beaucoup de contenu texte (HTML, CSS, JS)
- APIs JSON volumineuses
🔴 Quand ne pas l’utiliser :
- Contenu déjà compressé (images, vidéos)
- Flux temps réel (SSE, WebSocket) — voir note ci-dessous
Configuration minimale :
http: middlewares: compress: compress: {}Appliquer au lab :
whoami: labels: - "traefik.http.routers.whoami.middlewares=compress@file"✅ Vérifier :
# Demander gzipcurl -H "Accept-Encoding: gzip" -I http://whoami.localhost# → Content-Encoding: gzip
# Demander brotli (prioritaire si supporté)curl -H "Accept-Encoding: br, gzip" -I http://whoami.localhost# → Content-Encoding: brPièges fréquents :
- Compression sur des réponses tiny → overhead
- Compression + SSE → latence au lieu de temps réel
🟠 Variante avancée — Taille minimale :
compress-smart: compress: minResponseBodyBytes: 1024 # Compresser seulement si > 1 KB excludedContentTypes: - text/event-streamPriorité des algorithmes : Traefik choisit brotli (br) si le client le supporte, sinon gzip. Brotli offre une meilleure compression mais est plus lent.
Redirections
Section intitulée « Redirections »RedirectScheme — HTTP vers HTTPS
Section intitulée « RedirectScheme — HTTP vers HTTPS »🟢 Quand l’utiliser :
- Forcer HTTPS sur tous les services
🔴 Quand ne pas l’utiliser :
- Environnement de dev local sans certificat
Configuration minimale :
http: middlewares: redirect-https: redirectScheme: scheme: https permanent: true # 301 au lieu de 302✅ Vérifier :
curl -I http://whoami.localhost# → HTTP/1.1 301 Moved Permanently# → Location: https://whoami.localhost/RedirectRegex — Redirections par expression régulière
Section intitulée « RedirectRegex — Redirections par expression régulière »🟢 Quand l’utiliser :
- Rediriger
www.vers apex (ou inversement) - Migrations d’URLs complexes
🔴 Quand ne pas l’utiliser :
- Redirections simples (préférez RedirectScheme ou record DNS CNAME)
Configuration minimale :
http: middlewares: redirect-www: redirectRegex: regex: "^https://www\\.(.*)" replacement: "https://${1}" permanent: true✅ Vérifier :
curl -I https://www.example.com# → HTTP/1.1 301 Moved Permanently# → Location: https://example.comChaînage de middlewares
Section intitulée « Chaînage de middlewares »Créer une chain
Section intitulée « Créer une chain »Objectif : grouper plusieurs middlewares pour les réutiliser.
http: middlewares: # Middlewares unitaires rate-limit: rateLimit: average: 100 burst: 200
secure-headers: headers: frameDeny: true contentTypeNosniff: true
compress: compress: {}
# Chain qui les combine chain-web: chain: middlewares: - rate-limit - secure-headers - compressUtilisation :
whoami: labels: - "traefik.http.routers.whoami.middlewares=chain-web@file"Ordre dans une chain
Section intitulée « Ordre dans une chain »L’ordre dans la liste middlewares est l’ordre d’exécution :
chain: middlewares: - rate-limit # 1. Bloque les abus - basic-auth # 2. Vérifie l'identité - strip-prefix # 3. Transforme l'URL - secure-headers # 4. Ajoute headers - compress # 5. Compresse la réponseDépannage orienté symptômes
Section intitulée « Dépannage orienté symptômes »Symptôme : middleware ignoré
Section intitulée « Symptôme : middleware ignoré »Observations :
- Les headers attendus ne sont pas présents
- L’authentification ne se déclenche pas
Causes probables :
-
Nom mal orthographié — Vérifiez que le nom dans
middlewares:correspond exactement à la définition -
Mauvais provider — Un middleware File Provider se référence avec
@file, un Docker avec@docker:- middleware-name@file # File provider- middleware-name@docker # Docker provider -
Namespace Kubernetes — Le middleware doit être dans le même namespace ou référencé avec
namespace-name@kubernetescrd
Diagnostic :
# Lister les middlewares connus par Traefikcurl http://localhost:8080/api/http/middlewares | jq '.[].name'Symptôme : 401 Unauthorized inattendu
Section intitulée « Symptôme : 401 Unauthorized inattendu »Observations :
- L’utilisateur a des credentials valides mais reçoit 401
Causes probables :
-
Hash mal généré — Vérifiez que vous utilisez bcrypt (
htpasswd -nbB) -
$ non échappé — Dans Docker labels, doublez les
$:$$2y$$05$$... -
ForwardAuth : service auth inaccessible — Vérifiez que le service auth répond :
Fenêtre de terminal curl http://authelia:9091/api/verify
Symptôme : 429 Too Many Requests
Section intitulée « Symptôme : 429 Too Many Requests »Observations :
- Rate limit se déclenche pour des utilisateurs légitimes
Causes probables :
-
Limites trop agressives — Augmentez
averageetburst -
sourceCriterion mal configuré — Tous les utilisateurs partagent la même limite :
sourceCriterion:ipStrategy:depth: 0 # IP directe du client -
Derrière un proxy sans X-Forwarded-For — Toutes les requêtes semblent venir de la même IP
Symptôme : headers de sécurité absents
Section intitulée « Symptôme : headers de sécurité absents »Observations :
curl -Ine montre pas les headers attendus
Causes probables :
-
Middleware non attaché au routeur — Vérifiez le label
middlewares= -
Backend renvoie déjà ces headers — Traefik n’écrase pas les headers existants par défaut
-
Ordre des middlewares — Un autre middleware écrase les headers
Symptôme : ForwardAuth timeout (500)
Section intitulée « Symptôme : ForwardAuth timeout (500) »Observations :
- Erreur 500 avec “context deadline exceeded” dans les logs
Causes probables :
-
Service auth lent — Le service d’authentification met trop de temps
-
Mauvaise URL —
addresspointe vers un service inaccessible
Solution — Vérifiez la connectivité :
# Depuis le conteneur Traefikdocker exec -it traefik wget -q -O- http://authelia:9091/api/verifyCheck-list finale
Section intitulée « Check-list finale »Avant de déployer vos middlewares en production, vérifiez :
-
HTTPS activé — BasicAuth et headers de sécurité n’ont de sens qu’avec TLS
-
Ordre correct — Rate limit et IP filter avant l’authentification
-
Tests curl effectués — Chaque middleware validé individuellement
-
Logs consultés — Pas d’erreur dans
docker logs traefik -
Dashboard vérifié — Middlewares visibles dans l’API
À retenir
Section intitulée « À retenir »-
Un middleware est un filtre — il transforme, vérifie ou protège entre le client et le backend.
-
Bloquer tôt, transformer tard — rate limit avant auth, headers et compress en dernier.
-
Chaînez avec
chain— groupez les middlewares par cas d’usage (public, internal, api). -
Testez avec curl — chaque middleware a une commande de validation simple.
-
BasicAuth sans HTTPS = danger — préférez ForwardAuth + SSO en production.