Chapitre 9
Dépannage
Fiches d'incidents courants, chacune avec ses symptômes, son diagnostic et sa solution.
Concerne :Équipe techniqueHébergeur
Chaque fiche décrit un symptôme, la façon de le diagnostiquer et la solution. Les commandes se lancent sur le serveur, dans /opt/read/code.
Conseil
Avant toute remise en état importante, faites une sauvegarde (sudo /opt/read/code/deploy/sauvegarde.sh) et gardez une copie des journaux : ils disparaissent quand les conteneurs sont recréés.
Le certificat HTTPS n'est pas obtenu#
Symptôme. Le navigateur signale une connexion non sécurisée ou un certificat invalide ; le site ne répond pas en HTTPS.
Diagnostic.
docker compose logs --tail 200 caddy | grep -i -E "error|acme|challenge"Causes habituelles :
- le nom de domaine ne pointe pas (ou pas encore) vers le serveur : vérifiez les enregistrements
AetAAAAdepuis un autre poste (nslookup read.example.org) ; un enregistrementAAAAvers une autre machine suffit à faire échouer la validation ; - les ports 80 ou 443 sont fermés (pare-feu
ufw, pare-feu de l'hébergeur) ou occupés par un autre service ; - le domaine passe par un proxy ou un CDN ;
SITE_ADDRESScontient une faute, unhttps://ou un/final ;- trop d'essais : Let's Encrypt limite le nombre de demandes ; Caddy réessaie seul, plus tard.
Solution. Corrigez la cause, puis docker compose up -d (si .env a changé) ou docker compose restart caddy. Caddy redemande le certificat de lui-même.
Le conteneur de l'application est « unhealthy » ou redémarre en boucle#
Symptôme. docker compose ps montre app « unhealthy » ou « Restarting » ; le site répond 502.
Diagnostic.
docker compose logs --tail 200 app
docker compose ps -aChaîne de connexion 'ConnectionStrings:Read' manquanteou erreur d'authentification PostgreSQL pourread_app: le servicemigrationsn'a pas créé ou mis à jour le rôle (voir la fiche suivante), ouPOSTGRES_APP_PASSWORDa changé sans nouveauup.dbn'est pas « healthy » : la base est arrêtée, le disque est plein, ou le volume est endommagé.- Erreur au démarrage dans l'initialisation (référentiels, administrateur) : le message l'indique.
Solution. Corrigez la cause puis relancez l'ensemble : docker compose up -d. Si db est en cause, consultez docker compose logs db.
Les migrations échouent#
Symptôme. migrations est arrêté avec un code différent de 0 ; app ne démarre pas (il attend la réussite des migrations).
Diagnostic.
docker compose logs migrationsRemarque
Sur une base vide, une erreur SELECT … FROM "__EFMigrationsHistory" apparaît avant la création de cette table : elle est normale et n'arrête pas le service.
Causes possibles : POSTGRES_PASSWORD différent du mot de passe réel du compte propriétaire (il est fixé à la création du volume) ; nom de rôle POSTGRES_APP_USER invalide (lettres minuscules, chiffres et _ seulement) ; migration en conflit avec des données existantes.
Solution. Corrigez .env puis docker compose up -d. Si une migration d'une nouvelle version échoue sur les données, revenez à la version précédente (Retour arrière) et restaurez au besoin la sauvegarde d'avant le déploiement ; transmettez le message d'erreur à l'équipe de développement.
Le disque est plein#
Symptôme. Erreurs d'écriture, base arrêtée, dépôts de fichiers refusés, sauvegarde en échec.
Diagnostic.
df -h /
sudo du -sh /var/backups/read /var/lib/docker
docker system dfSolution.
- Supprimez les images Docker inutilisées :
docker image prune -f, et le cache de construction ancien :docker builder prune -f --filter until=720h. - Si les sauvegardes locales dominent et que la copie hors serveur est en place, réduisez
SAUVEGARDE_JOURSou supprimez à la main les dossiers les plus anciens de/var/backups/read. - Si besoin, agrandissez le disque chez l'hébergeur.
- Relancez
docker compose up -det vérifiez l'état des conteneurs.
Danger
Ne supprimez jamais de fichiers dans /var/lib/docker/volumes : ce sont les données de la plateforme.
Les e-mails ne partent pas#
Symptôme. Les utilisateurs ne reçoivent ni le lien « mot de passe oublié » ni les copies de notifications.
Diagnostic.
docker compose logs --tail 300 app | grep -i -E "e-mail|smtp"écrit dans la boîte d'envoi locale … aucun serveur SMTP réglé:EMAIL_HOTEest vide.- Erreur d'authentification ou de connexion : identifiant, mot de passe, port ou
EMAIL_SECURITEincorrects, ou port sortant bloqué par l'hébergeur. - Messages envoyés mais non reçus : l'adresse
EMAIL_EXPEDITEURn'est pas autorisée par le serveur SMTP, ou les enregistrements SPF/DKIM du domaine manquent (messages classés indésirables). - L'utilisateur n'a pas d'adresse e-mail dans son compte, ou a désactivé les copies par e-mail dans son profil.
Solution. Corrigez les variables EMAIL_*, puis docker compose up -d. Les notifications en attente sont envoyées par la tâche de fond qui tourne chaque minute.
L'heure affichée est fausse ou les connexions échouent par intermittence#
Symptôme. Dates décalées dans le journal, jetons du module hors ligne refusés, certificat jugé « pas encore valide ».
Diagnostic. timedatectl : System clock synchronized doit valoir yes.
Solution. Réactivez la synchronisation : sudo timedatectl set-ntp true. La plateforme enregistre les dates en UTC et les affiche à l'heure de Niamey : ne changez pas le fuseau des conteneurs.
Le mot de passe de l'administrateur est perdu#
Symptôme. Plus aucun administrateur ne peut se connecter.
Solution, dans l'ordre :
- Un autre administrateur réinitialise le mot de passe depuis l'écran Utilisateurs.
- Sinon, la personne utilise Mot de passe oublié sur la page de connexion ; le lien part à l'adresse e-mail du compte.
Sans serveur SMTP réglé, ce même e-mail est écrit dans le volume des fichiers déposés : affichez le plus récent pour y lire le lien (valable une heure) :
docker run --rm -v read-plateforme_app-donnees:/d:ro alpine:3.24 sh -c 'cat "$(ls -t /d/boite-envoi/*.eml | head -n 1)"'
Remarque
Après 5 échecs de connexion, un compte est bloqué 15 minutes : attendre suffit. La réinitialisation du mot de passe débloque aussi le compte.
ADMIN_EMAIL et ADMIN_MOT_DE_PASSE ne recréent un administrateur que s'il n'en existe aucun : ils ne servent pas à réinitialiser un compte existant.
Trop de requêtes (429) ou blocage d'un bureau entier#
Symptôme. Des utilisateurs reçoivent la page « Trop de tentatives » à la connexion.
Diagnostic. Plusieurs personnes derrière la même adresse IP publique (bureau, partage de connexion) partagent la limite de 10 tentatives de connexion par minute.
Solution. Attendre une minute suffit. Si le cas est fréquent, augmentez Securite__ConnexionsParMinute (Réglages avancés).
Toutes les adresses du journal d'audit sont identiques#
Symptôme. Le journal d'audit montre la même adresse IP pour tous les utilisateurs.
Diagnostic. Un relais placé devant Caddy (proxy ou CDN du gestionnaire DNS, répartiteur de charge de l'hébergeur) masque l'adresse des clients.
Solution. Passez l'enregistrement DNS en « DNS seulement ». Si un relais est indispensable, l'équipe de développement doit adapter Caddy et Securite__ReseauxProxy pour le reconnaître.
Une restauration d'essai échoue#
Symptôme. restaurer.sh --essai affiche ÉCHEC ou une erreur de contrôle des empreintes.
Diagnostic.
sha256sum: WARNING … did NOT match: un fichier de la sauvegarde est altéré ou incomplet (copie interrompue).- Différences de comptes : la sauvegarde ou sa restauration est incomplète.
Solution. Essayez la sauvegarde de la veille ou la copie hors serveur ; si plusieurs sauvegardes échouent, lancez une sauvegarde manuelle et observez son compte rendu (place disque, erreurs de pg_dump). Ne faites jamais une restauration réelle avec une sauvegarde dont l'essai a échoué.
Les utilisateurs voient une ancienne version du module hors ligne#
Symptôme. Après un déploiement, le module hors ligne d'un téléphone n'a pas les nouveautés.
Solution. Le module garde son application en cache pour fonctionner sans réseau. À la connexion suivante avec du réseau, il détecte la nouvelle version et propose Mettre à jour ; elle s'active aussi quand tous les onglets du module sont fermés. Voir Mise à jour du module.