- 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
14 KiB
OPERATIONS — Maintenance et opérations courantes
Procédures pour maintenir, dépanner, et faire évoluer l'infrastructure Seize.
🔍 Vérifications quotidiennes (5 min/jour)
Healthcheck rapide
# Tous les conteneurs sont-ils Up ?
sudo docker ps --format "table {{.Names}}\t{{.Status}}" | grep -v "Up"
# → Aucune ligne sauf le header = tout va bien
# Tous les sous-domaines répondent-ils en HTTPS ?
for domain in sso intranet git n8n portainer code status; do
echo -n "$domain : "
curl -sk -o /dev/null -w "%{http_code}\n" "https://$domain.seizeconsulting.com"
done
# → 200 ou 302 sur chaque ligne = OK
# → 500, 502, 503 = problème
# Espace disque restant
df -h /
# → Surveiller si > 80% utilisé
Logs récents
# Logs Traefik (erreurs uniquement)
sudo docker logs --tail 100 traefik 2>&1 | grep -i "error\|warn"
# Logs Zitadel (erreurs)
sudo docker logs --tail 100 zitadel-zitadel-api-1 2>&1 | grep -i "error\|level=err"
# Logs OAuth2-Proxy intranet (erreurs récentes)
sudo docker logs --tail 100 oauth2-proxy 2>&1 | grep -i "error"
📦 Backups
⚠️ État actuel : AUCUN backup automatique
À mettre en place en priorité.
Procédure backup manuel (à exécuter avant grosse modif)
# Créer un dossier de backup daté
BACKUP_DIR=~/backups/$(date +%Y%m%d-%H%M%S)
mkdir -p $BACKUP_DIR
# Backup Postgres (Gitea, n8n)
docker exec postgres pg_dumpall -U postgres > $BACKUP_DIR/postgres.sql
# Backup Postgres Zitadel (sa propre instance)
docker exec zitadel-postgres-1 pg_dumpall -U postgres > $BACKUP_DIR/postgres-zitadel.sql
# Backup volumes Docker (Gitea data, etc.)
sudo tar czf $BACKUP_DIR/gitea-data.tar.gz -C ~/docker/gitea data/
sudo tar czf $BACKUP_DIR/uptime-data.tar.gz -C ~/docker/uptime-kuma data/
sudo tar czf $BACKUP_DIR/portainer-data.tar.gz -C ~/docker/portainer data/
# Backup configs (.env, docker-compose.yml)
tar czf $BACKUP_DIR/configs.tar.gz -C ~/docker .
# Backup scripts furious-to-zitadel
tar czf $BACKUP_DIR/furious-scripts.tar.gz -C ~/ furious-to-zitadel/
echo "✅ Backup terminé dans $BACKUP_DIR"
ls -lh $BACKUP_DIR
Procédure backup automatique (à mettre en place)
Voir docs/09-troubleshooting.md section Backup automatisé.
🔄 Mises à jour
Mise à jour d'un service Docker
cd ~/docker/<service>
docker compose pull
docker compose up -d
Vérifier qu'une mise à jour ne casse rien
# 1. Backup avant
~/backup-manual.sh # script à créer si pas existant
# 2. Pull la nouvelle image
docker compose pull
# 3. Restart
docker compose down
docker compose up -d
# 4. Vérifier les logs
docker compose logs -f
# Ctrl+C pour quitter
# 5. Tester le service (login, fonctionnalités principales)
Mises à jour critiques à surveiller
| Service | Risque | Procédure |
|---|---|---|
| Traefik | Changement breaking config | Lire le CHANGELOG avant |
| Zitadel | Schema DB peut changer | Backup obligatoire avant |
| Postgres | Migration majeure | Backup + lire migration guide |
| OAuth2-Proxy | Changement de scopes/headers | Tester en dry-run |
➕ Ajouter un nouvel outil
Procédure standard (~1h)
1. Ajouter le record DNS
Chez le registrar : créer record A <outil>.seizeconsulting.com → IP du serveur.
2. Déployer l'outil (sans SSO)
mkdir -p ~/docker/<outil>
cd ~/docker/<outil>
# Créer docker-compose.yml
cat > docker-compose.yml << EOF
services:
<outil>:
image: <image>:<tag>
container_name: <outil>
restart: unless-stopped
networks:
- web
# PAS de labels Traefik ici → c'est OAuth2-Proxy qui sera exposé
networks:
web:
external: true
EOF
docker compose up -d
3. Créer l'application dans Zitadel
Console Zitadel → Projects → Infra Seize → New application :
- Type : Web
- Authentication Method : Basic
- Grant Types : Authorization Code
- Redirect URL :
https://<outil>.seizeconsulting.com/oauth2/callback - Token Settings :
- Auth Token Type : JWT
- User roles inside ID Token : ✅
- Include user's profile info in the ID Token : ✅
- Add user roles to the access token : ✅
Récupérer : Client ID + Client Secret.
4. Déployer un OAuth2-Proxy dédié
mkdir -p ~/docker/oauth2-proxy-<outil>
cd ~/docker/oauth2-proxy-<outil>
# docker-compose.yml (adapter depuis configs/oauth2-proxy/docker-compose.yml.template)
# .env (adapter depuis configs/oauth2-proxy/.env.example)
.env (variables à remplacer) :
OAUTH2_PROXY_PROVIDER=oidc
OAUTH2_PROXY_CLIENT_ID=<de Zitadel>
OAUTH2_PROXY_CLIENT_SECRET=<de Zitadel>
OAUTH2_PROXY_COOKIE_SECRET=<32 chars random>
OAUTH2_PROXY_OIDC_ISSUER_URL=https://sso.seizeconsulting.com
OAUTH2_PROXY_REDIRECT_URL=https://<outil>.seizeconsulting.com/oauth2/callback
OAUTH2_PROXY_UPSTREAMS=http://<outil>:<port_interne>
OAUTH2_PROXY_SCOPE=openid email profile urn:zitadel:iam:org:project:roles
OAUTH2_PROXY_EMAIL_DOMAINS=*
OAUTH2_PROXY_COOKIE_DOMAINS=.seizeconsulting.com
OAUTH2_PROXY_COOKIE_SECURE=true
OAUTH2_PROXY_HTTP_ADDRESS=0.0.0.0:4180
OAUTH2_PROXY_REVERSE_PROXY=true
OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER=true
OAUTH2_PROXY_PASS_ACCESS_TOKEN=true
OAUTH2_PROXY_SET_AUTHORIZATION_HEADER=true
OAUTH2_PROXY_SET_XAUTHREQUEST=true
OAUTH2_PROXY_WHITELIST_DOMAINS=.seizeconsulting.com
OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true
chmod 600 .env + docker compose up -d.
5. Ajouter une carte sur l'intranet
Éditer ~/docker/intranet/index.html et ajouter une nouvelle carte dans la section <a class="service-card"> :
<a class="service-card" data-app="<outil>" data-color="<color>" href="https://<outil>.seizeconsulting.com" target="_blank" rel="noopener">
<div class="card-header">
<div class="card-icon"><!-- SVG icon --></div>
<div class="card-arrow"><!-- SVG arrow --></div>
</div>
<div class="card-body">
<div class="card-title"><Nom de l'outil></div>
<div class="card-desc">Description courte</div>
<div class="card-meta">
<span class="card-url"><outil>.seizeconsulting.com</span>
<span class="card-tag">Catégorie</span>
</div>
</div>
</a>
6. Mettre à jour la matrice RBAC dans le JavaScript
Éditer le <script> RBAC dans index.html :
const ACCESS_MATRIX = {
"portainer": ["direction", "manager"],
"status": ["direction"],
// ...
"<outil>": ["direction", "manager"], // ← Ajouter ta nouvelle ligne
};
7. Restart de l'intranet
cd ~/docker/intranet
docker compose down
docker compose up -d
8. Tester
Se logger en incognito avec un user ayant accès → vérifier que la carte s'affiche et que le clic mène à l'outil avec SSO.
🗑️ Retirer un outil
Procédure inverse de l'ajout
# 1. Arrêter l'outil et son OAuth2-Proxy
cd ~/docker/<outil>
docker compose down
cd ~/docker/oauth2-proxy-<outil>
docker compose down
# 2. Archiver les configs (au cas où)
mv ~/docker/<outil> ~/docker/<outil>.archived-$(date +%Y%m%d)
mv ~/docker/oauth2-proxy-<outil> ~/docker/oauth2-proxy-<outil>.archived-$(date +%Y%m%d)
# 3. Supprimer l'application dans Zitadel
# Console → Projects → Infra Seize → Applications → <outil> → Delete
# 4. Retirer la carte sur l'intranet (HTML + matrice RBAC)
# Éditer ~/docker/intranet/index.html
# Restart : docker compose restart intranet
# 5. Optionnel : retirer le record DNS chez le registrar
👥 Gestion des utilisateurs
Ajouter un nouveau user manuellement
Quand un nouveau collaborateur arrive et n'est pas encore dans Furious :
Console Zitadel → Users → New → Human user :
- Email : prenom.nom@seizeconsulting.com
- Username : <trigramme> (ex: ABC)
- Prénom, Nom
- Cocher : Email verified, Password change required
- Generate password : oui (mdp temporaire 16 chars)
⚠️ Distribuer le mdp via Teams privé au nouveau collaborateur.
Désactiver un user (départ)
Console Zitadel → Users → <user> → Actions → Deactivate
⚠️ Ne PAS supprimer le user : ses traces dans les outils (commits Gitea, workflows n8n, etc.) seraient orphelines. Désactiver suffit.
Changer le rôle d'un user
Méthode UI (1 user)
Console Zitadel → Users → <user> → Authorizations → Edit roles
Méthode script (plusieurs users)
- Mettre à jour le mapping dans
assign-roles.py(variableJOB_TITLE_TO_ROLE) - Lancer :
cd ~/furious-to-zitadel source venv/bin/activate python3 assign-roles.py
⚠️ Le script ajoute les rôles, il ne retire pas les anciens. Pour retirer, utiliser l'UI ou un script custom.
Synchronisation périodique avec Furious
Workflow recommandé (à mettre en place) :
- Tous les jours : un cron exécute
read-all-users.shpour récupérer les users Furious - Compare avec les users Zitadel actuels
- Pour chaque diff :
- Nouveau dans Furious → créer dans Zitadel
- Départ détecté dans Furious (
departure_date != "0000-00-00") → désactiver dans Zitadel - Changement de
job_title→ réattribuer le rôle
⚠️ Pas encore automatisé. À mettre en place via n8n.
🔐 Rotation des secrets
Quand rotater ?
- 🔴 Immédiatement : si secret exposé (dans un commit Git, conversation IA, etc.)
- 🟡 Tous les 6 mois : pratique de bonne hygiène
- 🟢 Tous les ans : pour les secrets très internes (postgres root, etc.)
Procédure pour un secret OAuth2-Proxy (Client Secret Zitadel)
# 1. Aller dans Zitadel : Projects → Infra Seize → Applications → <outil>
# 2. Cliquer "Generate Client Secret" → copier le nouveau secret
# 3. Mettre à jour le .env d'OAuth2-Proxy
cd ~/docker/oauth2-proxy-<outil>
# Éditer .env, remplacer OAUTH2_PROXY_CLIENT_SECRET
# Sauvegarder dans le gestionnaire de mots de passe
# 4. Restart OAuth2-Proxy
docker compose down
docker compose up -d
Procédure pour la clé service account Zitadel
# 1. Console Zitadel → Users → furious-import-service → Keys
# 2. Supprimer l'ancienne clé (et l'invalider)
# 3. Créer une nouvelle clé (Type : JSON)
# 4. Télécharger la nouvelle clé immédiatement
# 5. Remplacer sur le serveur
scp <nouvelle_cle>.json admin@<serveur>:~/furious-to-zitadel/zitadelfuriousimportkey.json
ssh admin@<serveur>
chmod 600 ~/furious-to-zitadel/zitadelfuriousimportkey.json
# 6. Tester les scripts
cd ~/furious-to-zitadel
source venv/bin/activate
python3 assign-roles.py # Doit fonctionner avec la nouvelle clé
Procédure pour Postgres (Gitea/n8n)
⚠️ À faire HORS heures de bureau car les services s'arrêteront temporairement.
# 1. Générer un nouveau mdp
NEW_PWD=$(openssl rand -base64 32 | tr -d '+/=' | head -c 32)
echo "Nouveau mdp : $NEW_PWD"
# → Sauvegarder dans le gestionnaire de mots de passe
# 2. Changer le mdp dans Postgres
docker exec -it postgres psql -U postgres -c "ALTER USER gitea WITH PASSWORD '$NEW_PWD';"
# 3. Mettre à jour le .env de Gitea
nano ~/docker/gitea/.env
# Remplacer GITEA_DB_PASSWORD=$NEW_PWD
# 4. Restart Gitea
cd ~/docker/gitea
docker compose down
docker compose up -d
# 5. Tester Gitea
curl -sI https://git.seizeconsulting.com # Doit retourner 200 ou 302
🐛 Troubleshooting commun
Voir docs/09-troubleshooting.md pour une liste exhaustive.
"Mon SSO ne fonctionne plus, l'user est redirigé en boucle"
→ Probablement le bug Traefik authRequestHeaders=Cookie. Vérifier que ~/docker/traefik/dynamic.yml contient bien Cookie dans authRequestHeaders du middleware ForwardAuth.
"Le certificat Let's Encrypt a expiré"
→ Traefik renouvelle automatiquement. Si pas le cas :
# Vérifier les logs Traefik
sudo docker logs traefik 2>&1 | grep -i "letsencrypt\|certificate"
# Forcer le renouvellement
cd ~/docker/traefik
docker compose down
docker compose up -d
"Le script Python d'import échoue avec un 401 Unauthorized"
→ Le token Zitadel a expiré (1h) OU les droits du service account ont été révoqués.
# Vérifier que la clé JSON est valide
python3 -c "import json; data=json.load(open('zitadelfuriousimportkey.json')); print('UserId:', data.get('userId'), 'KeyId:', data.get('keyId'))"
# Vérifier dans Zitadel Console que le service account a toujours IAM_USER_MANAGER
"Un user ne peut pas se logger après avoir été créé"
→ Vérifier :
Email verifiedcocher dans son profil Zitadel- Si "Only authorized users can authenticate" est activé sur le project → il doit avoir un rôle
- MFA pas mal configuré → faire un reset MFA si bloqué
📊 Monitoring
Métriques à surveiller
| Métrique | Outil | Seuil d'alerte |
|---|---|---|
| Disponibilité des sous-domaines | Uptime Kuma | Down > 5 min |
| Taux d'erreur HTTP (5xx) | Logs Traefik | > 1% sur 5 min |
| Espace disque | df -h |
> 80% |
| RAM utilisée | free -h |
> 90% |
| CPU load | uptime |
> 4 (sur 4 vCPU) |
| Tentatives de login échouées | Logs Zitadel | > 100/heure (potentielle attaque) |
Mettre en place le monitoring
Uptime Kuma est déjà déployé. Ajouter des moniteurs pour :
- Chaque sous-domaine (HTTP check)
- Le serveur lui-même (ping)
- L'API Furious (HTTP check)
📞 Escalation
Quand appeler Philippe ?
- 🔴 Service critique down (Zitadel, Gitea, intranet) > 1h
- 🔴 Faille sécurité avérée
- 🔴 Perte de données
Quand appeler le support Scaleway ?
- 🔴 Serveur inaccessible (panne hardware)
- 🔴 Problème réseau Scaleway
Quand appeler le support Furious ?
- 🟡 API Furious down ou très lente
- 🟡 Permissions API qui ne fonctionnent pas
📝 Checklist hebdomadaire (5-10 min)
- Vérifier tous les conteneurs Up
- Vérifier l'espace disque < 80%
- Lire les alertes Uptime Kuma
- Vérifier les logs Traefik pour erreurs récurrentes
- Backup manuel des données critiques (si pas encore automatisé)
- Vérifier les certificats Let's Encrypt (expire dans > 7 jours)
📝 Checklist mensuelle (30 min)
- Faire un Docker prune des images inutilisées :
docker image prune -a - Vérifier les mises à jour disponibles :
apt list --upgradable - Auditer les users Zitadel (départs non synchronisés ?)
- Vérifier que les scripts Python fonctionnent toujours
- Lire les logs sécurité (tentatives de login échouées, etc.)