seize-infra-doc/docs/02-traefik-setup.md
Hedi Kalboussi 1e90a85359 Documentation initiale infra Seize — passation J7
- 6 docs racine (README, HANDOVER, ARCHITECTURE, DECISIONS, INSTALL, OPERATIONS)
- 9 docs thématiques dans docs/
- 10 templates docker-compose dans configs/
- 7 scripts Python/Shell d'import Furious vers Zitadel
- 2 matrices RBAC

Etat infra au 5 juin 2026 :
- 88 users Furious importes dans Zitadel
- 8 roles RBAC crees et attribues
- Intranet filtre les cartes selon role (Approche A)
- 7 outils SSO operationnels
2026-06-05 17:49:43 +00:00

7.4 KiB

02 — Traefik (Reverse Proxy)

Traefik est le point d'entrée unique de l'infrastructure. Il route le trafic vers les bons conteneurs et gère les certificats TLS automatiquement.


🎯 Rôle de Traefik

Fonction Description
Reverse proxy Route <sous-domaine>.seizeconsulting.com → conteneur correspondant
TLS termination Certificats Let's Encrypt automatiques pour tous les sous-domaines
HTTP → HTTPS redirect Force le HTTPS partout
ForwardAuth middleware Délègue l'auth à OAuth2-Proxy pour le SSO
Dashboard UI admin sur traefik.seizeconsulting.com

📁 Structure

~/docker/traefik/
├── docker-compose.yml
├── traefik.yml           # Config statique (entrypoints, providers)
├── dynamic.yml           # Config dynamique (middlewares, routers manuels)
└── letsencrypt/
    └── acme.json         # Certificats stockés (chmod 600)

📄 docker-compose.yml

services:
  traefik:
    image: traefik:v3.7.1
    container_name: traefik
    restart: unless-stopped
    command:
      - "--api.dashboard=true"
      - "--api.insecure=false"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=web"
      - "--providers.file.filename=/etc/traefik/dynamic.yml"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@seizeconsulting.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--log.level=INFO"
      - "--accesslog=true"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
      - ./dynamic.yml:/etc/traefik/dynamic.yml:ro
    networks:
      - web
    labels:
      # Dashboard sur traefik.seizeconsulting.com
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.rule=Host(`traefik.seizeconsulting.com`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.middlewares=traefik-auth"
      # Basic auth pour le dashboard (à remplacer par OAuth2-Proxy plus tard si on veut SSO)
      - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$xxxxxxxx$$xxxxxxxxxxxxxxxxxxxxxxx"

networks:
  web:
    external: true

⚠️ Remplacer :

  • admin@seizeconsulting.com par votre email Let's Encrypt
  • Le hash basicauth via htpasswd -nb admin <mdp>

📄 dynamic.yml (middlewares ForwardAuth)

http:
  middlewares:
    # Middleware ForwardAuth générique pour les outils protégés par OAuth2-Proxy
    oauth2-headers:
      forwardAuth:
        address: "http://oauth2-proxy:4180/oauth2/auth"
        trustForwardHeader: true
        # ⚠️ LIGNE CRITIQUE : sans 'Cookie', le SSO ne marche pas
        authRequestHeaders:
          - Cookie
          - Authorization
          - X-Forwarded-Host
          - X-Forwarded-Proto
          - X-Forwarded-Uri
        authResponseHeaders:
          - X-Auth-Request-User
          - X-Auth-Request-Email
          - X-Auth-Request-Preferred-Username
          - X-Auth-Request-Groups
          - X-Auth-Request-Access-Token
          - X-Forwarded-User
          - X-Forwarded-Email
          - X-Forwarded-Preferred-Username
          - X-Forwarded-Groups
          - Authorization

⚠️ Le Cookie dans authRequestHeaders est ESSENTIEL — sans ça, le SSO casse complètement (cf. DECISIONS.md D3).


🚀 Démarrage

cd ~/docker/traefik
# Créer l'acme.json
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json

# Lancer
docker compose up -d

# Vérifier les logs
docker compose logs -f
# Ctrl+C pour quitter

Vérifications

# Conteneur tourne ?
docker ps | grep traefik

# Logs propres ?
docker logs --tail 30 traefik 2>&1 | grep -i "error\|level=error"

# Accès au dashboard ?
curl -sI https://traefik.seizeconsulting.com
# Doit retourner 401 (demande de basic auth)

🌐 Comment ajouter un service derrière Traefik

Méthode 1 — Labels Docker (recommandé)

Sur le docker-compose.yml du service à exposer, ajouter ces labels :

services:
  myservice:
    image: ...
    networks:
      - web
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myservice.rule=Host(`myservice.seizeconsulting.com`)"
      - "traefik.http.routers.myservice.entrypoints=websecure"
      - "traefik.http.routers.myservice.tls.certresolver=letsencrypt"
      - "traefik.http.services.myservice.loadbalancer.server.port=8080"  # port interne du service
networks:
  web:
    external: true

⚠️ Important : le service doit être sur le réseau web partagé avec Traefik.

Méthode 2 — Avec SSO (via OAuth2-Proxy)

Pour les services qui n'ont pas de SSO natif, on ajoute OAuth2-Proxy entre Traefik et le service. Voir 04-oauth2-proxy-pattern.md.


🐛 Troubleshooting

"Certificat Let's Encrypt en échec"

Symptômes : navigateur dit "Connexion non sécurisée".

Causes possibles :

  1. DNS pas propagé : dig +short sub.seizeconsulting.com doit retourner l'IP du serveur
  2. Ports 80/443 bloqués : firewall + cloud provider
  3. Rate limit Let's Encrypt : trop de tentatives, attendre 1h
  4. acme.json corrompu :
    sudo rm letsencrypt/acme.json
    sudo touch letsencrypt/acme.json
    sudo chmod 600 letsencrypt/acme.json
    docker compose restart
    

"404 page not found" sur un sous-domaine

Causes possibles :

  1. Le service ciblé n'a pas les bons labels Traefik
  2. Le service n'est pas sur le réseau web
  3. Le port interne du service est incorrect dans loadbalancer.server.port
  4. La règle Host(...) est mal écrite (vérifier les backticks)

Vérifier dans le dashboard Traefik : https://traefik.seizeconsulting.com → Routers, Services.

"Bad Gateway 502"

Causes possibles :

  1. Le service backend est down
  2. Le service écoute sur un port différent de celui annoncé à Traefik
  3. Le service écoute sur 127.0.0.1 au lieu de 0.0.0.0
# Vérifier que le service répond bien sur le port interne attendu
docker exec -it traefik wget -qO- http://myservice:8080

"Le SSO ne marche plus depuis 5 min"

Vérifier la config ForwardAuth :

grep -A 10 "oauth2-headers" ~/docker/traefik/dynamic.yml
# La ligne "- Cookie" doit être présente dans authRequestHeaders

🔄 Mise à jour Traefik

cd ~/docker/traefik
docker compose pull
docker compose up -d

⚠️ Avant une major version (v2 → v3 par exemple) :

  • Lire le CHANGELOG
  • Tester en local d'abord
  • Backup de acme.json

📚 Liens utiles