Aller au contenu

Maintenance et depannage

Procedures de maintenance courante et resolution des problemes rencontres.


Mises a jour

DietPi

dietpi-update          # Met a jour DietPi + paquets
apt update && apt upgrade  # Mises a jour manuelles

Docker images

cd /mnt/ssd/config
docker compose pull    # Telecharge les nouvelles images
docker compose up -d   # Redeploy avec les nouvelles images
docker image prune -f  # Supprime les anciennes images

Watchtower surveille les mises a jour

Watchtower auto-update les services non-critiques et notifie via ntfy quand une mise a jour est disponible pour les services critiques (monitor-only).

Firmware RPi

rpi-eeprom-update      # Verifie les mises a jour firmware
rpi-update             # Met a jour le firmware (attention, peut casser)

Attention

rpi-update installe le firmware bleeding-edge. Preferer apt upgrade pour les mises a jour stables du kernel.


Verification post-reboot

Checklist apres un reboot :

  • [ ] SSD monte sur /mnt/ssd en rw
  • [ ] pcie_aspm=off actif (cat /sys/module/pcie_aspm/parameters/policy[off])
  • [ ] USB autosuspend a -1 (cat /sys/bus/usb/devices/*/power/autosuspend)
  • [ ] Quirks USB appliques (dmesg | grep "Quirks match")
  • [ ] Tous les containers Docker up (docker ps)
  • [ ] Pas de throttling (vcgencmd get_throttled = 0x0)
  • [ ] Temperature normale (vcgencmd measure_temp < 70°C)

SSD Argon Forty — deconnexions USB

Symptomes

  • EXT4-fs (sdX): shut down requested (2) dans dmesg
  • usb 2-2: USB disconnect suivi de re-enumeration
  • device offline error, dev sdX
  • Services Docker inaccessibles (Docker root sur le SSD)
  • Le device change de nom (sdasdbsdc) apres chaque reconnexion

Cause racine

Le bridge USB-SATA ASMedia ASM1156 (Argon Forty) est sensible a :

  1. PCIe ASPM — le mode powersave fait tomber le lien PCIe du controleur VL805 USB
  2. Connecteur USB interne — le dongle entre le socle SSD et le board RPi peut avoir un mauvais contact
  3. Port USB 3.0"Cannot enable. Maybe the USB cable is bad?" → fallback USB 2.0

Fixes appliques

Dans /boot/firmware/cmdline.txt :

pcie_aspm=off usbcore.autosuspend=-1 usb-storage.quirks=174c:1156:u
Parametre Effet
pcie_aspm=off Desactive le power management PCIe (fix principal)
usbcore.autosuspend=-1 Desactive l'USB autosuspend
usb-storage.quirks=174c:1156:u Force usb-storage au lieu de UAS pour le bridge ASMedia

Procedure de recovery manuelle

# 1. Verifier l'etat
dmesg | tail -20
lsblk
mount | grep ssd

# 2. Stopper Docker
systemctl stop docker docker.socket

# 3. Demonter le mount mort
umount -l /mnt/ssd

# 4. Verifier le filesystem
fsck.ext4 -y /dev/sdXX   # adapter au device actuel (lsblk)

# 5. Remonter
mount /mnt/ssd

# 6. Relancer Docker
systemctl start docker

Auto-recovery (homelab_monitor.sh)

Le script homelab_monitor.sh integre une recovery automatique en cas de deconnexion SSD :

  1. Stop Docker en premier (libere les file handles sur le SSD)
  2. Double unmount (umount -f + umount -l) pour nettoyer les mounts stale
  3. Attend que le device reapparaisse par UUID jusqu'a 60s + 3s de stabilisation
  4. fsck.ext4 -y sur le nouveau device (pas l'ancien)
  5. Verifie le code retour fsck (abort si >= 4)
  6. Remonte /mnt/ssd via fstab (UUID)
  7. Redemarre Docker, attend 10s pour les containers
  8. Notification ntfy "SSD RECOVERED" ou "RECOVERY FAILED"

Changement de device name (sda → sdb)

Le bridge ASMedia re-enumere le SSD avec un nouveau nom apres chaque deconnexion (sdasdbsdc). La recovery utilise l'UUID (pas le nom de device) pour retrouver le SSD quel que soit son nouveau nom. Le fstab utilise aussi l'UUID.

Rate limit : max 3 tentatives par heure. Si les 3 echouent, alerte "SSD Recovery EPUISE — intervention manuelle requise."

Investigation historique

Le support Argon a recommande :

  1. ~~Tester avec un cable USB 3.0 A-A court au lieu du dongle integre~~ Teste — meme probleme de deconnexion qu'avec le dongle
  2. Tester avec un SSD different (fanxiang S201 128 Go commande)
  3. ~~Verifier les logs pour ecarter un probleme logiciel~~ Elimine — aucun processus particulier au moment du disconnect

Conclusion provisoire : le bridge ASMedia ASM1156 est la cause, ni le cable ni le dongle. Le SSD de remplacement sera le test definitif.

Donnees SMART : UDMA_CRC_Error_Count = 4 (erreurs de communication SATA), pas de secteurs realloues.


Proxmox VE 9 — installation sur eMMC

Symptome

L'installeur Proxmox ne propose pas le device eMMC (mmcblk0) comme cible d'installation.

Cause

Proxmox ne supporte pas les devices mmcblk dans sa logique de partitionnement.

Workaround

Patcher l'installeur avant de lancer l'installation. Voir le guide complet.


Proxmox VE 9 — repos et popup

"No valid subscription"

Popup a chaque connexion a l'interface web.

Fix : le script proxmox-post-install.sh patche le fichier JS de l'interface web et redemarre pveproxy.

"Some suites are misconfigured"

Les fichiers .sources enterprise sont encore presents.

Fix : le script supprime les fichiers /etc/apt/sources.list.d/pve-enterprise.sources et ceph.sources.

"Warning: old suite bookworm"

Un fichier .list legacy avec la suite bookworm au lieu de trixie.

Fix : le script supprime /etc/apt/sources.list.d/pve-no-subscription.list (ancien format).


Docker containers — DNS interne et OIDC

Symptome

Les containers ne peuvent pas resoudre *.home.gabin-simond.fr (ex: auth.home.gabin-simond.fr). Erreur typique : dial tcp: lookup auth.home.gabin-simond.fr on 127.0.0.11:53: no such host

Cause

Les containers sur le reseau Docker proxy utilisent le DNS Docker interne (127.0.0.11) qui ne connait pas les rewrites AdGuard.

Fix

Ajouter dns: 192.168.1.28 dans le docker-compose.yml pour chaque container qui a besoin de resoudre des domaines locaux (Portainer, Beszel, Homepage, Vaultwarden).

services:
  mon-service:
    dns:
      - 192.168.1.28

Beszel — OIDC "Only superusers can perform this action"

Symptome

Login OIDC via Authelia renvoie 403 — Only superusers can perform this action.

Cause

PocketBase (backend de Beszel) bloque la creation de comptes via OAuth2 par defaut.

Workaround

  1. Aller dans /_/#/settings → desactiver la restriction admin-only creation
  2. Editer la collection users → API Rules → changer le "Create rule" en : @request.context = "oauth2"
  3. Reactiver la restriction admin-only
  4. Se connecter via OIDC (le compte est cree avec le role user)
  5. Aller dans /_/#/collectionsusers → promouvoir le compte en admin

Source : henrygd/beszel#291


Authelia — redirect_uri mismatch

Symptome

Erreur invalid_request : The 'redirect_uri' parameter does not match any of the OAuth 2.0 Client's pre-registered 'redirect_uris'.

Cause

L'URI de callback du service ne correspond pas exactement a ce qui est configure dans Authelia. Attention aux :

  • Trailing slash (/ vs pas de /)
  • Chemins specifiques (/api/oauth2-redirect, /identity/connect/oidc-signin)

Diagnostic

docker logs authelia | grep "redirect_uri"

Le log indique l'URI attendue par le client → copier cette URI exacte dans la config Authelia.

URIs correctes par service

Service redirect_uri
Proxmox https://galahad.home.gabin-simond.fr (et lancelot)
Portainer https://portainer.home.gabin-simond.fr/ (avec slash)
Beszel https://monitor.home.gabin-simond.fr/api/oauth2-redirect

Services inaccessibles via Tailscale VPN

Symptome

Certains services (ex: auth.home.gabin-simond.fr, vault.home.gabin-simond.fr) ne chargent pas depuis un client Tailscale, alors qu'ils fonctionnent en local.

Cause

Des DNS Rewrites statiques dans AdGuard (Filters > DNS Rewrites) ecrasent les user_rules conditionnelles. Les rewrites statiques sont appliquees en premier et renvoient toujours l'IP LAN (192.168.1.28), meme aux clients Tailscale qui ont besoin de l'IP Tailscale (100.97.239.90).

Fix

Supprimer toutes les entrees dans Filters > DNS Rewrites pour les domaines *.home.gabin-simond.fr. Le wildcard dans user_rules gere deja tous les sous-domaines avec le bon routage conditionnel (LAN vs Tailscale).

Voir Comment fonctionne le DNS pour le detail des regles.


Beszel — OIDC "Failed to fetch OAuth2 token"

Symptome

Login Authelia fonctionne (popup s'ouvre, auth OK) mais retour sur Beszel = page blanche. Console : ClientResponseError 401.

Causes (3 root causes combinees)

1. DNS Docker → NXDOMAIN pour auth.home.gabin-simond.fr

Le wildcard AdGuard ||home.gabin-simond.fr^$dnsrewrite=...,client=192.168.1.0/24 ne matche PAS les containers Docker (172.20.0.x). PocketBase ne peut pas resoudre auth.home... → token exchange echoue silencieusement.

Fix : ajouter un rewrite specifique (non filtre par client) dans AdGuard :

rewrites:
  - domain: auth.home.gabin-simond.fr
    answer: 192.168.1.28
    enabled: true

2. Image scratch Beszel = pas de CA certificates

Go HTTP client ne peut pas verifier le cert Let's Encrypt → TLS handshake echoue silencieusement.

Fix dans docker-compose.yml :

beszel:
  volumes:
    - /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
  environment:
    SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt

3. Subject ID mismatch dans PocketBase

Si les sessions OIDC Authelia sont purgees, le subject ID change. La table _externalAuths dans PocketBase garde l'ancien ID → mismatch → 401 apres token exchange reussi.

# Trouver le nouveau subject dans les logs Authelia (debug) :
docker logs authelia | grep "beszel.*subject"
# Mettre a jour PocketBase :
sqlite3 /path/to/beszel/data.db \
  "UPDATE _externalAuths SET providerId='<new_subject>' WHERE provider='oidc';"

Prevention

  • Ne JAMAIS purger les sessions OIDC Authelia sans re-aligner les _externalAuths
  • Garder les CA certs montes en permanence dans Beszel
  • Tester l'OIDC apres chaque rotation de secret

Beszel — hostname ancien affiche (pve1, gabin-simond.home)

Cause

Le beszel-agent cache le hostname au demarrage. Si le hostname systeme a ete renomme APRES le demarrage de l'agent, l'ancien nom persiste dans system_details.

Fix

# 1. Restart les agents sur chaque host
ssh galahad "sudo systemctl restart beszel-agent"
ssh lancelot "sudo systemctl restart beszel-agent"
docker restart beszel-agent  # penny

# 2. Si le hostname persiste, forcer en DB :
sqlite3 /path/to/beszel/data.db "UPDATE system_details SET hostname='galahad' WHERE hostname='pve1';"

Portainer — mot de passe perdu

Procedure de reset

# Trouver le bon volume
docker inspect portainer --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'

# Reset avec le helper (adapter le nom du volume)
docker compose stop portainer
docker run --rm -v config_portainer-data:/data portainer/helper-reset-password
docker compose up -d portainer

Le helper genere un nouveau mot de passe aleatoire.


Portainer — "failed opening store : timeout"

Cause

Un process Portainer fantome tient le verrou BoltDB. Typiquement apres un reset de mot de passe via --admin-password qui n'a pas ete arrete proprement.

Fix

fuser /path/to/portainer-data/portainer.db  # trouver le PID
kill -9 <PID>
docker start portainer

PVE — page blanche / chargement infini (Trixie)

Symptome

L'interface web Proxmox VE (galahad.home.* / lancelot.home.*) affiche une page blanche ou tourne a l'infini.

Causes possibles

1. DNS pointe vers l'IP directe Proxmox au lieu de Traefik

dig galahad.home.gabin-simond.fr @192.168.1.28
# Si renvoie 192.168.1.18 au lieu de 192.168.1.28 → le navigateur
# essaie :443 sur Proxmox (qui n'ecoute que sur :8006) → timeout

Fix : les rewrites AdGuard doivent pointer vers penny (192.168.1.28) pour que Traefik proxy vers :8006.

2. Fichier ExtJS manquant (symlink ext6-all.js)

Proxmox 9 sur Trixie : libjs-extjs installe ext-all.js mais pve-manager cherche ext6-all.js.

# Sur chaque node :
cd /usr/share/javascript/extjs/
ln -sf ext-all.js ext6-all.js
ln -sf ext-all-debug.js ext6-all-debug.js

3. Security headers incompatibles (CSP, COOP)

Content-Security-Policy ou Cross-Origin-Opener-Policy: same-origin appliques globalement cassent ExtJS + WebSocket. Les headers de securite ne doivent PAS etre appliques aux routes PVE.


Commandes utiles

Containers et services

docker ps -a                              # Etat de tous les conteneurs
docker logs <container_name> --tail 50    # Derniers logs
docker compose up -d <service_name>       # Relancer un service specifique
docker system df                          # Espace utilise par Docker
docker system prune -f                    # Nettoyer images/volumes inutilises

Temperature et alimentation

vcgencmd measure_temp                     # Temperature actuelle
vcgencmd get_throttled                    # 0x0 = tout va bien
Valeur throttled Signification
0x0 OK
0x50000 Throttling dans le passe
0x50005 Throttling actif + sous-voltage

Espace disque

df -h                    # Vue d'ensemble
docker system df         # Espace utilise par Docker
docker system prune -f   # Nettoyer images/volumes inutilises