- Deleted apps/web/src/utils/optimisticStoreUpdates.ts (unused file) - File was unused - no imports found in codebase - Mutations already use React Query's onMutate pattern - No TypeScript errors after deletion - Actions 4.4.1.2 and 4.4.1.3 complete
13 KiB
AUDIT COMPLET: veza-backend-api Broken Pipe & Fichier .env Manquant dans Incus
Date: 2025-01-27
Problème: veza-backend-api broken pipe. can't find .env file inside the dedicated incus container for the incus deploy
Priorité: P0 - CRITIQUE (bloque le déploiement)
1. RÉSUMÉ EXÉCUTIF
1.1 Problème Principal
Le service veza-backend-api déployé dans un conteneur Incus rencontre deux problèmes critiques:
- Broken Pipe Error: Erreurs de "broken pipe" lors de l'écriture des logs
- Fichier .env Manquant: L'application ne trouve pas le fichier
.envdans le conteneur
1.2 Impact
- ❌ Le service ne démarre pas correctement
- ❌ Les logs ne sont pas capturés par systemd/journald
- ❌ L'application ne peut pas charger les variables d'environnement
- ❌ Le déploiement Incus échoue silencieusement
2. ANALYSE DÉTAILLÉE
2.1 Architecture Actuelle du Déploiement
2.1.1 Fichiers de Configuration
config/incus/env/backend-api.env # Source (sur l'hôte)
↓ (copié via incus file push)
/etc/veza/backend-api.env # Destination (dans le conteneur)
2.1.2 Service Systemd
[Service]
WorkingDirectory=/opt/veza/backend-api
ExecStart=/opt/veza/backend-api/start-backend-api.sh
EnvironmentFile=/etc/veza/backend-api.env
StandardOutput=journal
StandardError=journal
2.1.3 Script Wrapper
#!/bin/bash
# start-backend-api.sh
source /etc/veza/backend-api.env
exec /usr/local/bin/veza-backend-api
2.1.4 Application Go
// main.go
_ = godotenv.Load() // Cherche .env dans le working directory
// config.NewConfig()
LoadEnvFiles(env) // Cherche .env.{env} et .env dans le working directory
2.2 Problèmes Identifiés
2.2.1 Problème #1: Incohérence des Chemins de Fichiers .env
Symptôme: L'application Go cherche un fichier .env dans /opt/veza/backend-api/ mais le fichier est à /etc/veza/backend-api.env
Cause Racine:
- Le script de déploiement copie le fichier à
/etc/veza/backend-api.env - Systemd charge les variables via
EnvironmentFile=/etc/veza/backend-api.env - Le wrapper script charge les variables via
source /etc/veza/backend-api.env - MAIS l'application Go fait
godotenv.Load()qui cherche.envdans le working directory (/opt/veza/backend-api/) - L'application Go fait aussi
LoadEnvFiles(env)qui cherche.env.productionet.envdans le working directory
Impact:
- Si les variables sont déjà chargées par systemd/wrapper,
godotenv.Load()échoue silencieusement (pas d'erreur si fichier absent) - Si les variables ne sont PAS chargées par systemd/wrapper, l'application ne trouve pas le fichier
.envet échoue
Preuve:
// veza-backend-api/cmd/api/main.go:50
_ = godotenv.Load() // Cherche .env dans le répertoire courant
// veza-backend-api/internal/config/env_loader.go:24
_ = godotenv.Load() // Cherche .env dans le répertoire courant
2.2.2 Problème #2: Broken Pipe Error
Symptôme: Erreurs "broken pipe" lors de l'écriture des logs
Cause Racine:
- Systemd/journald peut fermer le pipe stdout/stderr si le service démarre trop vite
- Le wrapper script peut écrire sur stdout/stderr avant que systemd ne soit prêt
- L'application Go peut essayer d'écrire sur stdout/stderr après que journald ait fermé le pipe
Impact:
- Les logs ne sont pas capturés correctement
- L'application peut crasher si les erreurs de broken pipe ne sont pas gérées
Preuve:
- Le code Go a déjà des mécanismes pour gérer les broken pipe (dans
logging/logger.go) - Mais le wrapper script et les premières lignes de
main.gopeuvent écrire sur stdout/stderr avant que le logger ne soit initialisé
2.2.3 Problème #3: Vérification Insuffisante du Fichier .env
Symptôme: Le script de déploiement vérifie que le fichier existe mais ne vérifie pas qu'il est accessible par l'application
Cause Racine:
- Le script
deploy-service-native.shvérifie que le fichier existe (test -f) - Le script vérifie que le fichier est lisible (
test -r) - MAIS le script ne vérifie pas que le fichier est accessible depuis le working directory de l'application
- Le script ne crée pas de lien symbolique ou copie vers le working directory
Impact:
- L'application Go ne peut pas charger le fichier
.envmême si les variables sont chargées par systemd
2.2.4 Problème #4: Ordre de Chargement des Variables d'Environnement
Symptôme: Les variables peuvent être chargées dans le mauvais ordre
Ordre Actuel:
- Systemd charge
/etc/veza/backend-api.env(viaEnvironmentFile) - Wrapper script charge
/etc/veza/backend-api.env(viasource) - Application Go charge
.envdans working directory (viagodotenv.Load()) - Application Go charge
.env.{env}et.env(viaLoadEnvFiles())
Problème:
- Si le fichier
.envn'existe pas dans le working directory,godotenv.Load()échoue silencieusement - Si les variables ne sont pas chargées par systemd/wrapper, l'application échoue
3. CAUSES RACINES
3.1 Cause Racine #1: Architecture Incohérente
- Problème: Mélange de deux approches (systemd EnvironmentFile + godotenv.Load())
- Solution: Choisir une seule approche et l'appliquer de manière cohérente
3.2 Cause Racine #2: Broken Pipe Non Géré au Démarrage
- Problème: Écriture sur stdout/stderr avant que journald ne soit prêt
- Solution: Rediriger stdout/stderr vers journald dès le début ou utiliser un logger qui gère les broken pipe
3.3 Cause Racine #3: Vérification Incomplète
- Problème: Le script de déploiement ne vérifie pas que l'application peut accéder au fichier .env
- Solution: Créer un fichier
.envdans le working directory ou modifier l'application pour chercher le fichier au bon endroit
3.4 Cause Racine #4: Documentation Manquante
- Problème: Pas de documentation claire sur où le fichier .env doit être et comment il est chargé
- Solution: Documenter clairement l'architecture de chargement des variables d'environnement
4. SCÉNARIOS D'ÉCHEC
4.1 Scénario 1: Fichier .env Non Copié
1. Script de déploiement échoue silencieusement lors de la copie
2. Fichier /etc/veza/backend-api.env n'existe pas
3. Systemd ne charge pas les variables (mais ne signale pas d'erreur si EnvironmentFile est optionnel)
4. Wrapper script échoue avec "No such file or directory"
5. Application ne démarre pas
4.2 Scénario 2: Fichier .env Non Lisible
1. Fichier copié mais permissions incorrectes
2. Systemd peut charger les variables (root)
3. Wrapper script peut charger les variables (root)
4. Application Go cherche .env dans working directory (n'existe pas)
5. Application démarre mais avec variables manquantes
4.3 Scénario 3: Broken Pipe au Démarrage
1. Systemd démarre le service
2. Wrapper script écrit sur stdout/stderr
3. Journald n'est pas encore prêt → broken pipe
4. Application Go essaie d'écrire sur stdout/stderr → broken pipe
5. Application crash ou logs perdus
4.4 Scénario 4: Variables Non Chargées
1. Fichier .env copié correctement
2. Systemd charge les variables
3. Wrapper script charge les variables
4. Application Go cherche .env dans working directory (n'existe pas)
5. Si variables critiques manquantes → application échoue
5. POINTS DE VÉRIFICATION
5.1 Vérifications à Effectuer
5.1.1 Dans le Conteneur
# Vérifier que le fichier existe
incus exec veza-backend-api -- test -f /etc/veza/backend-api.env && echo "OK" || echo "FAIL"
# Vérifier les permissions
incus exec veza-backend-api -- ls -la /etc/veza/backend-api.env
# Vérifier le contenu
incus exec veza-backend-api -- cat /etc/veza/backend-api.env
# Vérifier que systemd peut le charger
incus exec veza-backend-api -- systemctl show veza-backend-api --property=EnvironmentFiles
# Vérifier le working directory
incus exec veza-backend-api -- pwd
incus exec veza-backend-api -- ls -la /opt/veza/backend-api/
# Vérifier les variables d'environnement chargées
incus exec veza-backend-api -- systemctl show veza-backend-api --property=Environment
5.1.2 Logs Systemd
# Vérifier les logs du service
incus exec veza-backend-api -- journalctl -u veza-backend-api -n 50
# Vérifier les erreurs
incus exec veza-backend-api -- journalctl -u veza-backend-api -p err
# Vérifier les broken pipe
incus exec veza-backend-api -- journalctl -u veza-backend-api | grep -i "broken pipe"
5.1.3 Status du Service
# Vérifier le status
incus exec veza-backend-api -- systemctl status veza-backend-api
# Vérifier si le service est actif
incus exec veza-backend-api -- systemctl is-active veza-backend-api
# Vérifier les erreurs de démarrage
incus exec veza-backend-api -- systemctl status veza-backend-api | grep -i error
6. SOLUTIONS PROPOSÉES
6.1 Solution 1: Créer un Fichier .env dans le Working Directory (RECOMMANDÉ)
Avantages:
- Compatible avec l'application Go existante
- Pas de modification du code Go
- Simple à implémenter
Inconvénients:
- Duplication du fichier (mais acceptable pour la cohérence)
Implémentation:
- Modifier
deploy-service-native.shpour copier aussi le fichier vers/opt/veza/backend-api/.env - Vérifier que le fichier est créé et lisible
6.2 Solution 2: Modifier l'Application Go pour Chercher le Fichier au Bon Endroit
Avantages:
- Pas de duplication
- Architecture plus propre
Inconvénients:
- Modification du code Go
- Plus complexe à maintenir
Implémentation:
- Modifier
env_loader.gopour chercher le fichier à/etc/veza/backend-api.enven premier - Fallback vers
.envdans le working directory
6.3 Solution 3: Utiliser Uniquement Systemd EnvironmentFile
Avantages:
- Architecture simple
- Pas de duplication
- Variables chargées avant le démarrage de l'application
Inconvénients:
- Nécessite de supprimer
godotenv.Load()du code Go - Peut casser le développement local
Implémentation:
- Supprimer
godotenv.Load()demain.go - Supprimer
LoadEnvFiles()deconfig.NewConfig() - S'assurer que systemd charge toutes les variables nécessaires
6.4 Solution 4: Gérer les Broken Pipe au Démarrage
Avantages:
- Résout le problème des broken pipe
- Améliore la robustesse
Implémentation:
- Rediriger stdout/stderr vers journald dès le début du wrapper script
- S'assurer que le logger Go gère les broken pipe (déjà fait)
- Éviter d'écrire sur stdout/stderr avant que le logger ne soit initialisé
7. RECOMMANDATION FINALE
Solution Recommandée: Combinaison de Solution 1 + Solution 4
- Créer un fichier
.envdans le working directory pour compatibilité avec l'application Go - Gérer les broken pipe en redirigeant stdout/stderr vers journald dès le début
- Améliorer les vérifications dans le script de déploiement
- Documenter l'architecture de chargement des variables d'environnement
Raison:
- Compatible avec l'application Go existante
- Résout les deux problèmes (broken pipe + fichier .env)
- Minimal impact sur le code existant
- Facile à maintenir
8. RISQUES ET MITIGATION
8.1 Risque 1: Duplication du Fichier .env
Mitigation: Le fichier est petit et la duplication est acceptable pour la cohérence
8.2 Risque 2: Modification du Script de Déploiement
Mitigation: Tester le script sur un conteneur de test avant production
8.3 Risque 3: Régression sur le Développement Local
Mitigation: S'assurer que les modifications n'affectent pas le développement local
9. TESTS DE VALIDATION
9.1 Tests à Effectuer
-
Test 1: Déploiement Complet
./config/incus/deploy-service-native.sh backend-api ./config/incus/verify-deployment.sh -
Test 2: Vérification du Fichier .env
incus exec veza-backend-api -- test -f /etc/veza/backend-api.env incus exec veza-backend-api -- test -f /opt/veza/backend-api/.env -
Test 3: Vérification des Variables
incus exec veza-backend-api -- env | grep DATABASE_URL incus exec veza-backend-api -- env | grep JWT_SECRET -
Test 4: Vérification des Logs
incus exec veza-backend-api -- journalctl -u veza-backend-api -n 20 incus exec veza-backend-api -- journalctl -u veza-backend-api | grep -i "broken pipe" -
Test 5: Test de Santé
incus exec veza-backend-api -- curl -f http://localhost:8080/health
10. RÉFÉRENCES
10.1 Fichiers Concernés
config/incus/deploy-service-native.sh(lignes 315-358)config/incus/systemd/veza-backend-api.serviceconfig/incus/scripts/start-backend-api.shveza-backend-api/cmd/api/main.go(ligne 50)veza-backend-api/internal/config/env_loader.goveza-backend-api/internal/config/config.go(ligne 210)
10.2 Documentation
- Systemd EnvironmentFile: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=
- godotenv: https://github.com/joho/godotenv
- Incus file push: https://linuxcontainers.org/incus/docs/main/instances/#file-management
Fin de l'Audit