Maîtriser Traefik v3 en Reverse Proxy : Configuration Docker et Sécurisation
Traefik s’est imposé comme le standard pour le routage de conteneurs grâce à sa capacité de découverte dynamique. Dans cet article, nous allons décortiquer une configuration Traefik v3.6, conçue pour un environnement de self-hosting, du chiffrement TLS automatique et une délégation d’authentification.
L’objectif n’est pas simplement de copier-coller un fichier YAML, mais de comprendre chaque directive, chaque label, et la stratégie de sécurité sous-jacente (notamment l’usage d’un ForwardAuth).
1. Architecture et Concepts Clés
Avant d’analyser le code, rappelons le rôle de Traefik ici : il agit comme un Edge Router. Il intercepte tout le trafic entrant (ports 80 et 443), gère la terminaison TLS via Let’s Encrypt, et route les requêtes vers les conteneurs appropriés en se basant sur les Labels Docker.
Nous analyserons la stack selon trois axes :
- Configuration statique (le service Traefik lui-même).
- Sécurité et Auth (le service TinyAuth).
- Routing applicatif (comment exposer vos applications).
2. Lecture Commentée : La Configuration Statique
La configuration statique définit comment Traefik démarre et se connecte aux fournisseurs. Voici l’analyse du service traefik présent dans le docker-compose.yml.
Le bloc Service Traefik
services:
traefik:
image: traefik:v3.6
container_name: traefik
restart: always
# ...
Nous utilisons ici la version v3.6. C’est une bonne pratique de figer la version mineure pour éviter les breaking changes inattendus lors d’un docker pull. N’oubliez pas, “Latest is not a version” !
Les Commandes (Flags)
C’est ici que se joue le comportement du proxy. Regroupons-les par thématique pour la lisibilité :
a) Observabilité et API
command:
- --log.level=INFO
- --metrics.prometheus=true
- --api.insecure=true
- --api=true
- Logs & Métriques : Le niveau
INFOest standard. L’activation de Prometheus permet de scraper Traefik pour monitorer les entrypoints et routers. - API & Dashboard :
api.insecure=trueactive le dashboard sur le port 8080 sans authentification par défaut. - Point d’attention : En production, on préfère souvent désactiver le mode
insecureet router le dashboard via Traefik lui-même avec un middleware d’auth. Cependant, nous verrons plus bas que l’accès est restreint via le mapping de ports.
b) Providers (La découverte dynamique)
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --providers.file.directory=/traefik_dynamic
- --providers.file.watch=true
- Docker : Traefik écoute le socket Docker.
- ExposedByDefault=false : Crucial pour la sécurité. Par défaut, aucun conteneur n’est exposé. Il faudra explicitement ajouter le label
traefik.enable=truesur chaque service à publier. - File Provider : Permet de charger des configurations dynamiques (middlewares globaux, certificats TLS custom) depuis le dossier
/traefik_dynamic.
c) EntryPoints et Redirection HTTPS
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
Une configuration canonique : tout trafic arrivant sur le port 80 (web) est immédiatement redirigé vers le 443 (websecure) en HTTPS. Cela force une politique “Secure by Default”.
d) Certificats et ACME (Let’s Encrypt)
- --certificatesresolvers.myresolver.acme.httpchallenge=true
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.myresolver.acme.caserver=[https://acme-v02.api.letsencrypt.org/directory](https://acme-v02.api.letsencrypt.org/directory)
- --certificatesresolvers.myresolver.acme.email=benjamin.xxxxx@gmail.com
- --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
-
Resolver : Nommé
myresolver. -
Challenge : Utilise
httpChallenge. Traefik va temporairement servir un fichier sur le port 80 pour prouver à Let’s Encrypt qu’il possède le domaine. -
Note technique : Le
httpChallengeest simple mais ne permet pas de générer des certificats Wildcard (*.domaine.fr), qui nécessiteraient undnsChallenge. -
Stockage : Le fichier
acme.json(persistant via volume) contient les clés privées.
e) Logs d’accès (Configuration particulière)
- --accesslog=false
- --accesslog.format=json
- --accesslog.fields.defaultmode=keep
# ... (autres filtres)
- Observation : On note une configuration détaillée des champs (
User-Agentconservé,ServiceURLsupprimé), mais la directive globale est--accesslog=false. - Conséquence : Actuellement, aucun log d’accès n’est généré. Pour les activer, il suffirait de passer ce flag à
true. J’ai pour projet de récupérer les logs au format json et de les traîter au travers d’un stack ELK.
Ports et Réseaux
ports:
- 80:80
- 10.8.0.1:8080:8080/tcp
- 443:443
- Binding spécifique : Notez la ligne
10.8.0.1:8080:8080/tcp. C’est une mesure de sécurité qui compense le flag--api.insecure=true. Le dashboard n’est accessible que via l’interface réseau ayant l’IP10.8.0.1(mon VPN Wireguard), et non exposé publiquement.
networks:
- web
- back
Traefik est connecté à deux réseaux :
web: Le réseau public/DMZ où se situe les frontaux.back: Pour atteindre des services qui ne doivent pas être exposés directement mais que Traefik doit router.
3. Sécurisation avec TinyAuth (ForwardAuth)
Le fichier compose inclut un service d’authentification léger : TinyAuth.
tinyauth:
image: ghcr.io/steveiliop56/tinyauth:v3
# ... env vars ...
labels:
- traefik.enable=true
# Définition du routeur pour accéder à l'interface de TinyAuth
- traefik.http.routers.tinyauth.rule=host(`tinyauthv2.bracloud.fr`)
- traefik.http.routers.tinyauth.entrypoints=websecure
- traefik.http.routers.tinyauth.tls.certresolver=myresolver
# Définition du MIDDLEWARE
- traefik.http.middlewares.tinyauth.forwardauth.address=http://tinyauth:3000/api/auth/traefik
Le mécanisme ForwardAuth
C’est ici que la magie opère. La dernière ligne des labels définit un Middleware nommé tinyauth (implicitement rattaché au service container, mais utilisable globalement).
Le flux est le suivant :
- Une requête arrive sur une application protégée.
- Traefik voit le middleware
tinyauth. - Traefik met la requête en pause et contacte
http://tinyauth:3000/.... - Si TinyAuth répond 200 OK, Traefik laisse passer la requête vers l’application. Sinon, il redirige vers le login.
4. Exemples d’Intégration (Comment utiliser cette stack ?)
La configuration ci-dessus est le socle. Voici comment déployer des applications derrière ce Traefik.
A. Exemple Minimal (Whoami)
Pour exposer un service simple sur le réseau web.
services:
whoami:
image: traefik/whoami
networks:
- web
labels:
# 1. Activation explicite (car exposedbydefault=false)
- "traefik.enable=true"
# 2. Règle de routage
- "traefik.http.routers.whoami.rule=Host(`whoami.bracloud.fr`)"
# 3. Entrée HTTPS et Certificat
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.tls.certresolver=myresolver"
B. Exemple Avancé : Service Interne Protégé
Imaginons une application métier sensible (internal-app) qui se trouve sur le réseau back et que l’on veut protéger avec TinyAuth.
services:
webapp:
image: my-company/app
networks:
- back
labels:
- "traefik.enable=true"
# Indiquer à Traefik quel réseau utiliser pour contacter le conteneur
# (Nécessaire car Traefik est sur 'web' et 'back', et l'app seulement sur 'back')
- "traefik.docker.network=back"
- "traefik.http.routers.app-sec.rule=Host(`admin.bracloud.fr`)"
- "traefik.http.routers.app-sec.entrypoints=websecure"
- "traefik.http.routers.app-sec.tls.certresolver=myresolver"
# APPLICATION DU MIDDLEWARE D'AUTH
# Syntax: nom-middleware@provider
- "traefik.http.routers.app-sec.middlewares=tinyauth@docker"
Note importante : Le middleware se nomme
tinyauthet a été défini dans les labels du conteneurtinyauth(donc via le providerdocker). On l’appelle donc viatinyauth@docker.
5. Points de Vigilance & Debug
Si vous déployez cette stack, voici les points critiques à vérifier pour éviter les erreurs “404 Page Not Found” ou “Bad Gateway”.
- Réseaux Externes : Le
docker-compose.ymldéclare les réseauxwebetbackcommeexternal: true. Vous devez les créer avant de lancer la stack :
docker network create web
docker network create back
- **Permissions
acme.json**: Le fichier monté/etc/letsencrypt/acme.json(ou le dossier) doit avoir les permissions correctes (généralementchmod 600) pour que Traefik puisse y écrire les clés privées. - DNS : Le
httpChallengeimpose que le domaine (ex:tinyauthv2.bracloud.fr) pointe vers l’IP publique du serveur et que le port 80 soit ouvert et redirigé vers ce conteneur. - Conflit de ports : Vérifiez qu’aucun autre processus (Apache, Nginx système) n’écoute déjà sur le port 80 ou 443 de la machine hôte.
Conclusion
Cette configuration de Traefik v3.6 est robuste. Elle sépare proprement les responsabilités : Traefik gère la cryptographie et le routage, TinyAuth gère l’identité, et Docker gère le cycle de vie des applications.
L’usage de --providers.docker.exposedbydefault=false et la liaison du dashboard sur une IP spécifique (10.8.0.1) démontrent une approche “Security by Design”.
Actuellement ingénieur DevOps/Architecte Cloud, j’étais initialement interessé par l’administration système et grâce aux entreprises dans lesquelles j’ai pu travailler Oxalide et maintenant Claranet j’ai eu la chance de découvrir l’univers du Cloud et de l’automatisation.
Je me suis décidé a publier ce blog pour vous faire partager ma passion mais également pour enrichir avec modestie tout ce que l’on peut trouver sur internet. Bonne lecture !