seize-infra-doc/docs/09-troubleshooting.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

487 lines
11 KiB
Markdown

# 09 — Troubleshooting
> Problèmes fréquents rencontrés et leurs solutions.
---
## 🔍 Démarrage de tout diagnostic
Avant d'essayer n'importe quoi, vérifier :
```bash
# 1. Conteneurs en route
sudo docker ps
# 2. Espace disque
df -h /
# 3. Mémoire libre
free -h
# 4. Charge système
uptime
# 5. Logs Traefik récents (souvent la source des problèmes)
sudo docker logs --tail 50 traefik
```
---
## 🔴 Problèmes critiques
### "Tout est down, je ne peux plus accéder à rien"
#### Diagnostic
```bash
# SSH au serveur
ssh hedi@<server>
# Vérifier Docker
sudo systemctl status docker
sudo docker ps | wc -l
# Doit afficher > 20 (24 conteneurs attendus)
# Vérifier ports 80/443
sudo netstat -tlnp | grep -E "80|443"
# Vérifier les certificats Let's Encrypt
sudo ls -la ~/docker/traefik/letsencrypt/
```
#### Causes possibles
**Cause 1 — Docker daemon down** :
```bash
sudo systemctl restart docker
sudo docker compose -f ~/docker/traefik/docker-compose.yml up -d
# Démarrer dans l'ordre : Traefik, puis Zitadel, puis les autres
```
**Cause 2 — Disque plein** :
```bash
# Nettoyer Docker
sudo docker system prune -a --volumes
# Nettoyer logs si > 1 Go
sudo du -sh /var/lib/docker/containers/*/
sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log
```
**Cause 3 — IP du serveur a changé** :
- Vérifier DNS : `dig +short sso.seizeconsulting.com`
- Si IP différente → mettre à jour DNS chez le registrar
---
### "Le SSO ne fonctionne plus depuis 5 minutes"
Symptôme : tous les outils SSO renvoient une boucle de redirection ou un "Bad Gateway".
#### Diagnostic — Vérifier dans cet ordre
**1. Zitadel répond ?**
```bash
curl -sI https://sso.seizeconsulting.com
# Doit retourner 200 ou 302
```
Si non : `docker logs zitadel-zitadel-api-1 --tail 50`
**2. Traefik ForwardAuth marche ?**
```bash
grep -A 8 "authRequestHeaders" ~/docker/traefik/dynamic.yml
# La ligne "- Cookie" doit être présente
```
**3. OAuth2-Proxy de l'outil tourne ?**
```bash
sudo docker ps | grep oauth2-proxy
# Tous doivent être Up
```
**4. Logs OAuth2-Proxy ?**
```bash
sudo docker logs --tail 50 oauth2-proxy
sudo docker logs --tail 50 oauth2-proxy-n8n
# Chercher : "error", "unauthorized", "context deadline exceeded"
```
#### Solutions courantes
**Solution 1** : Restart de Traefik
```bash
cd ~/docker/traefik
docker compose down
docker compose up -d
```
**Solution 2** : Restart d'OAuth2-Proxy de l'outil concerné
```bash
cd ~/docker/oauth2-proxy-<outil>
docker compose down
docker compose up -d
```
**Solution 3** : Vérifier que les certificats TLS sont OK
```bash
echo | openssl s_client -connect sso.seizeconsulting.com:443 2>/dev/null | openssl x509 -noout -dates
# notAfter doit être dans > 7 jours
```
---
### "Le bug Traefik Cookie est revenu (boucle de redirect)"
C'est **le** bug historique. Cf. [DECISIONS.md D3](../DECISIONS.md).
#### Fix immédiat
Vérifier que `~/docker/traefik/dynamic.yml` contient :
```yaml
http:
middlewares:
oauth2-headers:
forwardAuth:
address: "http://oauth2-proxy:4180/oauth2/auth"
authRequestHeaders:
- Cookie # ← CRITIQUE
- Authorization
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
```
Si la ligne `- Cookie` manque → l'ajouter, puis :
```bash
cd ~/docker/traefik
docker compose restart
```
---
## 🟡 Problèmes courants
### "Le certificat Let's Encrypt va expirer / a expiré"
Traefik renouvelle automatiquement. Si pas le cas :
```bash
# Vérifier les logs Let's Encrypt
sudo docker logs traefik 2>&1 | grep -i "letsencrypt\|acme" | tail -20
# Causes possibles :
# 1. Rate limit Let's Encrypt (trop de tentatives) → attendre 1h
# 2. DNS pas correct → vérifier dig
# 3. Port 80 bloqué → vérifier firewall
# Forcer le renouvellement
cd ~/docker/traefik
docker compose down
docker compose up -d
```
⚠️ Cas critique : `acme.json` corrompu :
```bash
sudo cp letsencrypt/acme.json letsencrypt/acme.json.backup
sudo rm letsencrypt/acme.json
sudo touch letsencrypt/acme.json
sudo chmod 600 letsencrypt/acme.json
docker compose restart
```
→ Recrée tous les certificats (peut prendre 5 min).
---
### "Un user ne peut pas se logger"
#### Vérifier dans cet ordre
**1. Le compte existe-t-il dans Zitadel ?**
- Console Zitadel → Users → Search par email
- Status doit être "Active" (pas "Inactive" ou "Deleted")
**2. L'email est-il vérifié ?**
- Console → User → General → Email verified ?
- Si non : Actions → Resend verification (mais SMTP doit être configuré)
- Ou : Set as verified manually
**3. Le MFA est-il bloqué ?**
- Si l'user a perdu son téléphone : Reset MFA
- Console → User → Multi-factor authentication → Remove
**4. Lockout actif ?**
- Console → User → Activity → vérifier les failed attempts
- Reset : Actions → Unlock
**5. L'user a-t-il un rôle ?**
- Si "Only authorized users" est coché sur le project, il faut un rôle
- Console → User → Authorizations → Add role
---
### "Le script Python d'import échoue"
#### Erreur 401 / 403
```bash
cd ~/furious-to-zitadel
source venv/bin/activate
# Vérifier la clé JSON
python3 -c "
import json
data = json.load(open('zitadelfuriousimportkey.json'))
print('UserId:', data.get('userId'))
print('KeyId:', data.get('keyId'))
"
# Si erreur → la clé est corrompue, en régénérer une
# Vérifier les permissions du service account
# Console Zitadel → Users → furious-import-service → IAM Members
# Doit avoir IAM_USER_MANAGER
```
#### Erreur 400 sur certains users
```bash
# Voir les détails dans le log
tail -100 import.log | grep -B 2 "ERROR"
# Causes courantes :
# - Email invalide dans Furious (espaces, caractères spéciaux)
# - Mdp trop court / ne respecte pas la policy
# - Username déjà existant
```
#### Erreur de connexion Furious
```bash
./test-auth.sh
# Doit retourner un JSON valide
# Si 401 → identifiants Furious à régénérer
# Si timeout → API Furious peut être down, vérifier status
```
---
### "L'intranet ne montre pas les bonnes cartes"
Voir [07-rbac-intranet.md](./07-rbac-intranet.md) section Troubleshooting.
Rapide :
1. Console JS (F12) → vérifier le log `[RBAC] User: ... | Rôle: ...`
2. Si rôle null → `roles-mapping.json` à régénérer
3. Si email = `__USER_EMAIL__` → nginx sub_filter pas appliqué
---
### "Le conteneur xxx redémarre en boucle"
```bash
# Voir les logs
sudo docker logs <container> --tail 50
# Voir le statut détaillé
sudo docker inspect <container> --format '{{.State.Health}}'
# Causes courantes :
# 1. Healthcheck failed → vérifier la commande de healthcheck
# 2. Erreur de config (mauvais env) → vérifier .env
# 3. Volume manquant ou permissions → vérifier les paths
# 4. Port déjà utilisé → docker compose down + up
# Voir les events Docker récents
sudo docker events --since 10m
```
---
### "Espace disque saturé"
```bash
# Voir où va l'espace
sudo du -sh /var/lib/docker/* | sort -h
sudo du -sh /home/*
# Nettoyer Docker
sudo docker system prune -a --volumes
# ⚠️ Supprime tout ce qui n'est pas utilisé activement
# Nettoyer les logs Docker
sudo find /var/lib/docker/containers -name "*-json.log" -exec truncate -s 0 {} \;
# Configurer la rotation des logs (à mettre dans /etc/docker/daemon.json) :
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
# Restart Docker après modif
sudo systemctl restart docker
```
---
## 🟢 Problèmes mineurs
### "L'image d'un conteneur est obsolète"
```bash
cd ~/docker/<service>
docker compose pull
docker compose up -d
```
### "Comment voir les logs en temps réel ?"
```bash
docker compose logs -f
# Ctrl+C pour quitter
```
### "Comment redémarrer juste un service sans toucher les autres ?"
```bash
sudo docker restart <container_name>
# Plus rapide qu'un docker compose
```
### "Comment exécuter une commande dans un conteneur ?"
```bash
sudo docker exec -it <container> sh
# ou bash si dispo
```
---
## 🔧 Débogage avancé
### Nginx Diagnostic (debug RBAC)
⚠️ **Procédure temporaire** — supprimer immédiatement après usage.
Pour voir ce que les headers HTTP contiennent réellement :
```bash
# Créer une config nginx diagnostic
cat > ~/docker/intranet/nginx-diagnostic.conf << 'EOF'
events {}
http {
server {
listen 80;
location /debug {
add_header Content-Type text/plain;
return 200 "=== Headers reçus ===
X-Forwarded-User: $http_x_forwarded_user
X-Forwarded-Email: $http_x_forwarded_email
X-Forwarded-Preferred-Username: $http_x_forwarded_preferred_username
X-Forwarded-Groups: $http_x_forwarded_groups
Authorization: $http_authorization
";
}
location / { try_files $uri /index.html =404; }
}
}
EOF
# Modifier docker-compose pour utiliser cette config
nano ~/docker/intranet/docker-compose.yml
# Ajouter le volume : ./nginx-diagnostic.conf:/etc/nginx/nginx.conf:ro
# Restart
docker compose up -d
# Accéder à : https://intranet.seizeconsulting.com/debug
# (en étant logué)
# ⚠️ AVANT DE FERMER : restaurer la config normale !
rm ~/docker/intranet/nginx-diagnostic.conf
# Remettre nginx-rbac.conf dans docker-compose.yml
```
### Décoder un token JWT
Si tu as un token et veux voir son contenu (claims, exp, etc.) :
```bash
# Méthode 1 : jwt.io (en ligne, ATTENTION ne pas coller de vrais tokens)
# Méthode 2 : ligne de commande
TOKEN="<ton_jwt>"
echo $TOKEN | cut -d "." -f2 | base64 -d 2>/dev/null | python3 -m json.tool
```
### Vérifier la communication réseau entre 2 conteneurs
```bash
sudo docker exec -it traefik wget -qO- http://intranet:80
sudo docker exec -it oauth2-proxy wget -qO- http://intranet:80
```
Si erreur → vérifier que les conteneurs partagent un réseau Docker commun.
### Voir les connexions actives
```bash
sudo ss -tunlp | grep -E "80|443"
# Connexions en cours
sudo netstat -anp | grep ESTABLISHED | grep ":443" | wc -l
```
---
## 📋 Checklist quand quelque chose ne va pas
- [ ] Tous les conteneurs `Up` ? → `sudo docker ps`
- [ ] DNS OK ? → `dig +short <domain>`
- [ ] HTTPS valide ? → `curl -sI https://<domain>`
- [ ] Logs Traefik sans erreur ? → `docker logs --tail 50 traefik | grep -i error`
- [ ] Logs OAuth2-Proxy sans erreur ? → `docker logs --tail 50 oauth2-proxy*`
- [ ] Espace disque OK ? → `df -h /`
- [ ] Mémoire OK ? → `free -h`
- [ ] Authentification Zitadel OK depuis incognito ?
- [ ] Vérifier que rien n'a été modifié récemment (fichier .yml ou .env)
---
## 📞 Quand escalader
### Vers Philippe (sponsor)
- Service critique down > 30 min
- Demande de modification d'architecture
- Validation d'une décision business
### Vers le support Scaleway
- Serveur inaccessible (panne réseau ou hardware)
- Quota dépassé sur le compte
- Problème de facturation
### Vers le support Furious
- API Furious down ou très lente
- Permissions API qui ne fonctionnent pas malgré une bonne config
- Problèmes de données RH (départs mal renseignés, etc.)
### Vers la communauté Zitadel
- Discord Zitadel : https://discord.gg/zitadel
- Issues GitHub : https://github.com/zitadel/zitadel
- Forum : https://community.zitadel.com/
---
## 📚 Liens vers les docs internes
- [INSTALL.md](../INSTALL.md) — Procédure d'install from scratch
- [OPERATIONS.md](../OPERATIONS.md) — Maintenance et opérations courantes
- [HANDOVER.md](../HANDOVER.md) — Actions urgentes à mener
- [DECISIONS.md](../DECISIONS.md) — Anti-patterns à éviter