Maîtriser Traefik v3 en Reverse Proxy : Configuration Docker et Sécurisation

déc. 30, 2025·
Benjamin Rabiller
Benjamin Rabiller
· 6 min. de lecture

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 :

  1. Configuration statique (le service Traefik lui-même).
  2. Sécurité et Auth (le service TinyAuth).
  3. 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 INFO est standard. L’activation de Prometheus permet de scraper Traefik pour monitorer les entrypoints et routers.
  • API & Dashboard : api.insecure=true active 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 insecure et 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=true sur 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 httpChallenge est simple mais ne permet pas de générer des certificats Wildcard (*.domaine.fr), qui nécessiteraient un dnsChallenge.

  • 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-Agent conservé, ServiceURL supprimé), 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’IP 10.8.0.1 (mon VPN Wireguard), et non exposé publiquement.
    networks:
      - web
      - back

Traefik est connecté à deux réseaux :

  1. web : Le réseau public/DMZ où se situe les frontaux.
  2. 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 :

  1. Une requête arrive sur une application protégée.
  2. Traefik voit le middleware tinyauth.
  3. Traefik met la requête en pause et contacte http://tinyauth:3000/....
  4. 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 tinyauth et a été défini dans les labels du conteneur tinyauth (donc via le provider docker). On l’appelle donc via tinyauth@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”.

  1. Réseaux Externes : Le docker-compose.yml déclare les réseaux web et back comme external: true. Vous devez les créer avant de lancer la stack :
docker network create web
docker network create back
  1. **Permissions acme.json** : Le fichier monté /etc/letsencrypt/acme.json (ou le dossier) doit avoir les permissions correctes (généralement chmod 600) pour que Traefik puisse y écrire les clés privées.
  2. DNS : Le httpChallenge impose 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.
  3. 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”.

Benjamin Rabiller
Auteurs
DevOps/Cloud Architect

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 !