Debian 13 « Dependency failed » au démarrage : trouver le service unique qui bloque l’amorçage (cas n°29)

Cet article vous a aidé ?

Vous redémarrez une machine Debian 13 pour une tâche courante — mise à jour du noyau, firmware, un changement « rapide » de stockage — et elle revient avec le message jovial :
« Dependency failed ». L’invite de connexion n’arrive jamais, ou vous vous retrouvez en mode emergency à fixer un curseur clignotant et vos choix de vie.

L’astuce, c’est que systemd échoue rarement « le système ». Il échoue sur une unité, et une unité (ou une petite chaîne) suffit à bloquer l’amorçage. Votre travail consiste à identifier
le service unique qui empêche le démarrage, puis décider de le réparer, l’isoler ou rendre l’amorçage résilient.

Ce que signifie réellement « Dependency failed » dans systemd

systemd est un ordonnanceur de dépendances. Il transforme « démarrer la machine » en un graphe orienté d’unités (services, mounts, sockets, devices, targets).
Quand vous voyez « Dependency failed », vous voyez typiquement le symptôme en aval, pas la cause en amont.

Exemple : remote-fs.target peut échouer parce qu’une unique unité .mount a échoué, qui peut échouer parce qu’un device n’a pas été trouvé,
ce qui peut être dû à une mapping LUKS non déverrouillée, ce qui peut être dû à l’absence d’un fichier-clé à ce moment-là. systemd vous dira poliment
« dependency failed » à chaque relais. C’est comme entendre « la réunion est annulée » et essayer de déboguer tout l’agenda de l’entreprise.

Trois relations d’unités qui importent pendant l’amorçage

  • Requires= — dépendance forte. Si A Requires=B et B échoue, A échoue.
  • Wants= — dépendance souple. Si B échoue, A peut quand même continuer.
  • After=/Before= — ordonnancement seulement. N’implique pas la dépendance, mais peut créer des chaînes d’attente qui ressemblent à des blocages.

La plupart des blocages de démarrage présentés comme « Dependency failed » se résument à l’un de ces cas : un mount qui ne peut pas monter, un device qui n’apparaît jamais, une attente network-online,
ou une importation de stockage qui expire. Trouvez cette unité unique, et vous aurez le fil à tirer.

Blague #1 : systemd n’est pas « lent » ; il est juste extrêmement engagé à attendre cette unique chose que vous aviez promis qu’elle existerait.

Playbook de diagnostic rapide (faire ceci en premier)

C’est la séquence à haute valeur informationnelle quand vous avez une console (physique, IPMI ou console VM) et que vous devez trouver vite le coupable. Vous cherchez
l’unité qui est soit en échec, soit en attente indéfinie.

1) Accédez à un shell sans perdre de temps

Si vous êtes bloqué sur un splash, basculez vers un autre TTY (souvent Ctrl+Alt+F2). Si vous êtes en mode emergency, vous avez déjà un shell.
Si vous ne pouvez pas vous connecter, utilisez le mode de récupération dans GRUB ou ajoutez systemd.unit=emergency.target pour ce démarrage.

2) Identifiez ce qui a échoué lors du démarrage précédent

Exécutez journalctl -b -1 -p err (si vous avez redémarré) ou journalctl -b -p err (démarrage courant). Vous voulez la première erreur,
pas la dernière plainte.

3) Demandez à systemd ce qui a bloqué le chemin critique de démarrage

systemd-analyze critical-chain pointe l’unité qui a dominé le temps de démarrage. Si vous voyez un mount ou un network-online target bloqué pendant 1–2 minutes,
c’est votre bloquant. Si vous voyez un service « en attente », inspectez ses dépendances avec systemctl list-dependencies.

4) Confirmez l’unité unique et sa cause en amont

Pour cette unité, exécutez systemctl status UNIT puis journalctl -u UNIT -b. Si c’est un mount : vérifiez /etc/fstab.
Si c’est du stockage : vérifiez la présence du device. Si c’est network-online : vérifiez que la pile réseau utilisée est bien celle attendue.

5) Prenez une décision : corriger, contourner ou isoler

  • Corriger maintenant : corriger fstab, déverrouiller LUKS, importer le pool, corriger le fichier d’unité.
  • Contourner maintenant : commenter temporairement une ligne fautive dans fstab, ajouter nofail, ou masquer une unité non critique.
  • Isoler : démarrer dans multi-user.target sans la cible problématique, ou utiliser le mode emergency pour reprendre le contrôle.

Votre objectif est d’abord la disponibilité, la perfection après. Le système se fiche que votre montage NFS soit « important » s’il empêche SSH de démarrer.

Faits intéressants et contexte historique (pour votre modèle mental)

  1. systemd n’a pas seulement remplacé SysV init ; il a remplacé la philosophie du démarrage. Plutôt que des scripts linéaires, le démarrage est devenu un graphe de dépendances avec jobs et timeouts.
  2. L’expression « Dependency failed » est systemd qui reporte une propagation d’échec de job, pas une défaillance de type « kernel panic ». C’est de haut niveau et généralement réparable sans réinstaller.
  3. Debian a adopté systemd par défaut dans Debian 8 (Jessie), après des années de débat. L’impact opérationnel principal : moins de « mystery sleeps » dans les scripts init, plus d’ordonnancement explicite.
  4. Les targets comme network-online.target existent parce que « réseau configuré » et « réseau utilisable » sont des états différents ; beaucoup de services dépendent à tort du second.
  5. remote-fs.target et local-fs.target sont des points de coordination, pas des « services réels ». Un seul mauvais montage peut les prendre en otage.
  6. La gestion des mounts par systemd est étroitement liée à /etc/fstab. Une coquille là peut se manifester comme une unité en échec, pas comme un message convivial de mount.
  7. LUKS et dm-crypt sont généralement orchestrés au démarrage par l’initramfs et des unités systemd ; un fichier-clé manquant peut devenir un « dependency failed » à deux sauts de la vraie cause.
  8. La configuration journald par défaut de Debian a historiquement cherché un compromis entre usage disque et forensique. Si les logs sont seulement volatiles, vous pouvez perdre les preuves après un reset brutal.

Une idée fiable paraphrasée de W. Edwards Deming : « les résultats d’un système sont majoritairement déterminés par le système, pas par l’effort héroïque. » Cela s’applique au démarrage aussi — corrigez le système de dépendances, pas seulement la panne du jour.

La méthode « un seul blocage » : isoler l’unité qui fige le démarrage

« Dependency failed » est bruyant mais peu utile. La question utile est : quelle unité est la première dans la chaîne de défaillance et/ou quelle unité est la plus longue dans la critical chain ?
Ce sont souvent les mêmes, mais pas toujours.

Deux motifs que vous verrez

Motif A : une unité échoue rapidement, et d’autres unités échouent par conséquence

C’est le cas propre. Exemple : mnt-data.mount échoue parce que l’UUID n’existe pas. Ensuite local-fs.target signale un échec de dépendance,
et vous tombez en mode emergency.

Motif B : une unité n’échoue pas ; elle attend jusqu’au timeout

C’est le cas « ça semble bloqué ». Exemple : systemd-networkd-wait-online.service attend 2 minutes pour une liaison qui ne se lève jamais.
Le système finit par démarrer, mais tardivement, et vous aurez des erreurs de dépendance si d’autres services exigent « online » plutôt que « configured ».

Règle opérationnelle : incriminez la première unité en échec en amont, pas la target

Quand une target échoue, ce n’est presque jamais la faute de la target. La target est une boîte aux lettres. La lettre à l’intérieur est un mount qui a échoué, une importation qui a échoué,
un chemin de device obsolète, ou un service avec une dépendance forte qu’il ne devrait pas avoir.

Le moyen le plus rapide de trouver « le service unique » est :
(1) lister les unités en échec,
(2) inspecter la critical chain,
(3) lire le journal pour cette unité,
(4) cartographier le graphe de dépendances juste assez pour voir ce qui manque réellement.

Tâches pratiques (commandes, ce que la sortie signifie, la décision à prendre)

Ce sont des commandes de terrain que vous pouvez exécuter sur Debian 13. Chaque tâche inclut ce que vous regardez et la décision qui suit. Utilisez-les dans l’ordre si possible.
Quand le système est à moitié démarré, préférez journalctl et systemctl plutôt que des suppositions.

Task 1 — Lister les unités en échec (votre première présélection)

cr0x@server:~$ systemctl --failed
  UNIT                              LOAD   ACTIVE SUB    DESCRIPTION
● mnt-data.mount                    loaded failed failed /mnt/data
● systemd-networkd-wait-online.service loaded failed failed Wait for Network to be Configured

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit state, i.e. generalization of SUB.
SUB    = The low-level unit state, values depend on unit type.

2 loaded units listed.

Ce que ça signifie : Vous avez des suspects concrets. Ignorez les « targets » à moins qu’elles ne soient les seules choses listées.
Décision : choisissez l’unité qui correspond au symptôme de démarrage : le mode emergency pointe souvent vers des mounts ; des démarrages longs pointent souvent vers wait-online.

Task 2 — Voir ce qui a bloqué le temps de démarrage (critical chain)

cr0x@server:~$ systemd-analyze critical-chain
graphical.target @2min 4.112s
└─multi-user.target @2min 4.112s
  └─remote-fs.target @2min 3.900s
    └─mnt-nfs.mount @2min 3.880s +2min
      └─network-online.target @3.870s
        └─systemd-networkd-wait-online.service @1.500s +2.360s
          └─systemd-networkd.service @1.200s +250ms
            └─systemd-udevd.service @900ms +280ms
              └─systemd-tmpfiles-setup-dev.service @650ms +220ms
                └─kmod-static-nodes.service @420ms +200ms
                  └─systemd-journald.socket @380ms
                    └─system.slice @370ms

Ce que ça signifie : mnt-nfs.mount a consommé 2 minutes. C’est votre goulot d’étranglement, même si « Dependency failed » pointe ailleurs.
Décision : investiguez ce mount et pourquoi il dépend de network-online ; décidez s’il doit être nofail ou monté à la demande.

Task 3 — Montrer les lignes d’erreur exactes du démarrage courant

cr0x@server:~$ journalctl -b -p err --no-pager
Mar 12 08:41:02 server systemd[1]: mnt-data.mount: Mount process exited, code=exited, status=32/n/a
Mar 12 08:41:02 server systemd[1]: mnt-data.mount: Failed with result 'exit-code'.
Mar 12 08:41:02 server systemd[1]: Failed to mount /mnt/data.
Mar 12 08:41:02 server systemd[1]: local-fs.target: Dependency failed for Local File Systems.
Mar 12 08:41:10 server systemd-networkd-wait-online[412]: Timeout occurred while waiting for network connectivity.

Ce que ça signifie : Il y a au moins deux problèmes indépendants : un mount local en échec et un timeout d’attente réseau.
Décision : corrigez d’abord les mounts locaux si vous êtes en mode emergency ; corrigez wait-online ensuite si le démarrage est seulement lent.

Task 4 — Inspecter le statut d’une unité suspecte (ce que systemd pense s’être passé)

cr0x@server:~$ systemctl status mnt-data.mount --no-pager
× mnt-data.mount - /mnt/data
     Loaded: loaded (/etc/fstab; generated)
     Active: failed (Result: exit-code) since Wed 2025-03-12 08:41:02 UTC; 2min 12s ago
      Where: /mnt/data
       What: UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20
      Tasks: 0 (limit: 9250)
     Memory: 0B
        CPU: 8ms
     Error: 32 (Mount failure)
Mar 12 08:41:02 server systemd[1]: Mounting /mnt/data...
Mar 12 08:41:02 server mount[771]: mount: /mnt/data: special device UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20 does not exist.
Mar 12 08:41:02 server systemd[1]: mnt-data.mount: Mount process exited, code=exited, status=32/n/a
Mar 12 08:41:02 server systemd[1]: mnt-data.mount: Failed with result 'exit-code'.

Ce que ça signifie : C’est une unité de mount générée depuis /etc/fstab, et l’UUID n’est pas présent.
Décision : confirmez si le disque a disparu, a été renommé, n’a pas été déchiffré, ou si l’UUID a changé ; corrigez fstab en conséquence.

Task 5 — Confirmer que le device existe (ne faites pas confiance à fstab)

cr0x@server:~$ lsblk -f
NAME        FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1      vfat   FAT32       9C2B-1A1B                             504.7M     1% /boot/efi
├─sda2      ext4   1.0         6e6a86fb-4d93-4b8b-9b62-6a0c9b99afc2  712.4M    22% /boot
└─sda3      crypto 2           1f7c0a2c-3f9f-4e5a-9d3c-6d7f8e9a1b2c
  └─cryptroot
            ext4   1.0         2b1c4d9a-9d10-4d0a-ae91-5f8b21c4b1a1   38.9G    41% /
sdb
└─sdb1      ext4   1.0   DATA  9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d

Ce que ça signifie : L’UUID dans fstab ne correspond pas à ce qui est sur disque. Le filesystem DATA est présent mais avec un UUID différent.
Décision : mettez à jour /etc/fstab avec l’UUID correct (ou utilisez LABEL=DATA si votre discipline d’étiquetage est fiable).

Task 6 — Inspecter /etc/fstab soigneusement (et avec pessimisme)

cr0x@server:~$ sed -n '1,200p' /etc/fstab
# /etc/fstab: static file system information.
UUID=2b1c4d9a-9d10-4d0a-ae91-5f8b21c4b1a1 /         ext4  errors=remount-ro 0 1
UUID=6e6a86fb-4d93-4b8b-9b62-6a0c9b99afc2 /boot     ext4  defaults          0 2
UUID=9C2B-1A1B /boot/efi vfat  umask=0077         0 1
UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20 /mnt/data ext4  defaults          0 2

Ce que ça signifie : Une ligne référence un UUID qui n’existe pas.
Décision : si /mnt/data est optionnel pour le démarrage, ajoutez nofail,x-systemd.device-timeout=5s ou passez à l’automount ; si c’est indispensable, corrigez l’UUID et validez la chaîne de devices.

Task 7 — Tester les mounts sans redémarrer (attraper les erreurs en sécurité)

cr0x@server:~$ mount -a
mount: /mnt/data: can't find UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20.

Ce que ça signifie : Le problème est reproductible en dehors du démarrage. Bien — déboguer pendant le boot est horrible.
Décision : corrigez l’entrée fstab ; puis relancez mount -a jusqu’à ce que tout soit propre.

Task 8 — Pour les blocages network-online : voir qui en dépend

cr0x@server:~$ systemctl list-dependencies --reverse network-online.target
network-online.target
● ├─mnt-nfs.mount
● ├─remote-fs.target
● └─docker.service

Ce que ça signifie : Votre montage NFS et Docker forcent « online ». Cela peut être inutile s’ils tolèrent « network configured ».
Décision : découplez les services non critiques de network-online.target, ou corrigez le vrai problème de connectivité si l’état « online » est réellement nécessaire.

Task 9 — Vérifier la configuration du wait-online (les timeouts sont une politique)

cr0x@server:~$ systemctl cat systemd-networkd-wait-online.service
# /lib/systemd/system/systemd-networkd-wait-online.service
[Unit]
Description=Wait for Network to be Configured
Documentation=man:systemd-networkd-wait-online.service(8)
DefaultDependencies=no
Conflicts=shutdown.target
Before=network-online.target shutdown.target

[Service]
Type=oneshot
ExecStart=/lib/systemd/systemd-networkd-wait-online --timeout=120
RemainAfterExit=yes

[Install]
WantedBy=network-online.target

Ce que ça signifie : Le timeout par défaut peut être long. 120 secondes ressemble à un blocage lors d’un incident.
Décision : si votre environnement a des liaisons intermittentes, fixez un timeout plus court ou cessez d’exiger network-online pour des services qui peuvent retenter plus tard.

Task 10 — Voir si votre pile réseau est réellement networkd

cr0x@server:~$ systemctl is-enabled systemd-networkd NetworkManager
enabled
disabled

Ce que ça signifie : Vous utilisez networkd, donc wait-online est pertinent. Si NetworkManager était activé, vous voudriez l’unité wait NM à la place.
Décision : assurez-vous de ne pas avoir le mauvais « wait-online » pour la pile réseau que vous utilisez. Les décalages mènent à des timeouts inutiles.

Task 11 — Construire un graphe de dépendances pour l’unité suspecte (portée chirurgicale)

cr0x@server:~$ systemctl list-dependencies --all mnt-data.mount
mnt-data.mount
● ├─system.slice
● ├─-.mount
● ├─dev-disk-by\x2duuid-2f2c3a5b\x2d8d5e\x2d4e1b\x2db4d2\x2d2e1b1f4d2f20.device
● └─local-fs-pre.target

Ce que ça signifie : Ce mount attend directement une unité device qui n’existe pas.
Décision : trouvez pourquoi l’unité device n’est pas créée (disque manquant, UUID erroné, chiffrement non ouvert, pilote manquant).

Task 12 — Valider la découverte des devices (udev et messages noyau)

cr0x@server:~$ dmesg -T | tail -n 30
[Wed Mar 12 08:40:41 2025] sd 1:0:0:0: [sda] 1000215216 512-byte logical blocks: (512 GB/477 GiB)
[Wed Mar 12 08:40:41 2025] sd 2:0:0:0: [sdb] 1953525168 512-byte logical blocks: (1.00 TB/931 GiB)
[Wed Mar 12 08:40:42 2025] EXT4-fs (sdb1): mounted filesystem 9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d ro with ordered data mode
[Wed Mar 12 08:40:42 2025] EXT4-fs (sdb1): re-mounted 9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d rw

Ce que ça signifie : Le disque existe et l’UUID du filesystem est visible. Le problème vient de votre configuration, pas de la détection matérielle.
Décision : mettez à jour les références (UUID/LABEL) et envisagez d’ajouter des garde-fous (automount, nofail) pour les mounts non critiques.

Task 13 — Contourner temporairement un mount non critique en échec (récupérer la machine)

cr0x@server:~$ cp -a /etc/fstab /etc/fstab.bak
cr0x@server:~$ sed -i 's|^UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20|# UUID=2f2c3a5b-8d5e-4e1b-b4d2-2e1b1f4d2f20|' /etc/fstab
cr0x@server:~$ systemctl daemon-reload

Ce que ça signifie : Vous avez désactivé le mount pour l’instant. C’est un geste pragmatique, pas une faute morale.
Décision : redémarrez pour restaurer les services de base ; puis corrigez le mount proprement pendant une fenêtre contrôlée.

Task 14 — Rendre le mount résilient au lieu de bloquer le démarrage

cr0x@server:~$ grep -n '/mnt/data' /etc/fstab
12:UUID=9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d /mnt/data ext4 nofail,x-systemd.device-timeout=5s,x-systemd.automount 0 2

Ce que ça signifie : Ce mount ne bloquera pas le démarrage ; il montera à l’accès, et si le disque manque il ne vous enverra pas en mode emergency.
Décision : appliquez cela seulement aux mounts qui ne sont pas requis pour que l’OS fonctionne. Les bases de données et filesystems root ne sont pas « nofail ».

Task 15 — Pour emergency mode causé par fstab : vérifier la vue de systemd sur local-fs

cr0x@server:~$ systemctl status local-fs.target --no-pager
× local-fs.target - Local File Systems
     Loaded: loaded (/lib/systemd/system/local-fs.target; static)
     Active: failed (Result: dependency) since Wed 2025-03-12 08:41:02 UTC; 3min ago
       Docs: man:systemd.special(7)
Mar 12 08:41:02 server systemd[1]: local-fs.target: Dependency failed for Local File Systems.

Ce que ça signifie : La target est une victime. La vraie défaillance est une unité .mount sous-jacente.
Décision : arrêtez de fixer local-fs.target du regard ; revenez aux unités .mount en échec et corrigez-les.

Task 16 — Si le journal manque : vérifier la persistance de journald

cr0x@server:~$ ls -ld /var/log/journal
ls: cannot access '/var/log/journal': No such file or directory

Ce que ça signifie : Les logs peuvent être volatils. Après un redémarrage, la preuve a disparu.
Décision : activez le journal persistant sur les serveurs où la forensique de démarrage compte (la plupart). Sinon vous déboguez à l’aveugle.

Task 17 — Activer le journal persistant (pour que la prochaine fois soit moins bête)

cr0x@server:~$ sudo mkdir -p /var/log/journal
cr0x@server:~$ sudo systemd-tmpfiles --create --prefix /var/log/journal
cr0x@server:~$ sudo systemctl restart systemd-journald

Ce que ça signifie : Journald commencera à écrire des logs persistants (sous réserve de configuration et d’espace disque).
Décision : confirmez la politique d’utilisation du disque ; sur des racines petites, définissez des limites pour éviter de remplir /.

Cas n°29 : une chaîne typique de blocage au démarrage sur Debian 13

Voyons concrètement ce que signifie « identifier le service unique qui bloque le démarrage ». Le cas n°29 est un schéma que je vois souvent sur des hôtes Debian
qui font « un peu de tout » : disque de données local, quelques montages distants, et un service qui exige que le réseau soit parfait avant de démarrer.

Le jeu de symptômes

  • Sur la console : « A start job is running for /mnt/data » ou « Dependency failed for Local File Systems. »
  • Parfois on tombe en mode emergency, parfois le système démarre après ~2 minutes.
  • Après le démarrage : systemctl --failed montre un mount en échec et éventuellement un échec wait-online.

La chaîne de cause racine (comment ça arrive)

Quelqu’un a remplacé un disque, restauré depuis une sauvegarde, ou recréé un filesystem. L’UUID a changé. L’ancien UUID est resté dans /etc/fstab.
systemd a généré une unité de mount pour cette entrée et a tenté de la satisfaire pendant le démarrage. Il n’a pas trouvé le device ; le mount a échoué.
Comme le mount était traité comme requis (par défaut), local-fs.target a échoué et la séquence d’amorçage a pris la sortie dramatique vers le mode emergency.

Séparément, il y avait un montage NFS qui utilisait _netdev et systemd a traduit cela en nécessité du réseau. Une unité ou deux ont tiré network-online.target,
qui a entraîné systemd-networkd-wait-online.service. Sur un hôte sans câble branché (ou avec VLAN mal configuré),
wait-online a expiré au bout de 120 secondes. Ce n’est pas une « erreur » humaine ; c’est une politique que vous aviez oubliée.

Alors quel est « le service unique » qui bloque l’amorçage ?

Dans ce cas, c’est mnt-data.mount quand vous tombez en mode emergency. La ligne « Dependency failed » mentionne local-fs.target,
mais le bloqueur est l’unité de mount générée depuis /etc/fstab.

Si vous ne tombez pas en mode emergency mais que le démarrage est lent, le service unique est souvent systemd-networkd-wait-online.service ou un mount distant
qui attend derrière lui.

Votre diagnostic doit correspondre à l’impact opérationnel :
arrêt brutal au démarrage → corriger la dépendance forte (généralement des mounts locaux) ;
démarrage lent → supprimer les dépendances online inutiles, raccourcir les timeouts, ou rendre les mounts automount/nofail.

Blague #2 : Rien ne dit « haute disponibilité » comme un serveur qui refuse de démarrer tant qu’un partage distant qu’il n’utilise jamais n’est pas joignable.

Trois mini-histoires en entreprise (ce qui arrive réellement)

1) L’incident causé par une mauvaise hypothèse : « les UUID sont éternels »

Une entreprise SaaS de taille moyenne exécutait Debian sur une petite flotte de workers stateful. Ils avaient un disque de données monté sur /srv/data, référencé par UUID dans /etc/fstab.
L’équipe ops aimait les UUID parce que les noms de device comme /dev/sdb1 sont capricieux — l’ordre de branchement change, les contrôleurs réordonnent, chaos.

Lors d’un renouvellement matériel, un technicien a cloné des disques et « nettoyé » des partitions. Le filesystem a été recréé plutôt que cloné bit-à-bit.
Personne n’a remarqué car le point de montage existait et le répertoire semblait correct sur le banc de test. L’UUID a changé.

Le premier reboot en production après une mise à jour du noyau a été brutal. Plusieurs workers sont tombés en mode emergency avec « Dependency failed for Local File Systems. »
L’ingénieur de garde a d’abord poursuivi la mauvaise piste : il a vu local-fs.target échouer et a supposé que systemd était « cassé ».
Il a essayé de redémarrer des targets comme s’il s’agissait de services. C’est comme redémarrer un tableur pour corriger une faute dans la cellule B7.

La correction fut simple : mettre à jour les UUID dans /etc/fstab. La leçon n’était pas « ne pas utiliser les UUID ». La leçon était de traiter l’identité du stockage comme une configuration
qui doit être validée après une maintenance. Ils ont ajouté une vérification pré-redémarrage qui compare les entrées de fstab avec la sortie de lsblk -f et refuse d’avancer
quand un UUID référencé est absent.

Personne n’a été viré. Mais tout le monde a arrêté de dire « c’est juste un reboot ».

2) L’optimisation qui s’est retournée contre eux : « faire démarrer les services le plus tôt possible »

Une autre organisation — entreprise, contrainte conformité, beaucoup d’outils internes — voulait des temps de démarrage plus rapides pour un appliance basé sur Debian.
Quelqu’un a regardé le diagramme de démarrage et a décidé que l’attente réseau était du « temps perdu ». Ils ont désactivé le wait-online et supprimé les dépendances sur network-online.target.
Le démarrage fut plus rapide. Les métriques semblaient excellentes. La présentation a été approuvée.

Puis la réalité est arrivée. L’appliance exécutait un service qui nécessitait une IP stable et le DNS avant de pouvoir s’enregistrer auprès d’un contrôleur central.
Sans attendre que le réseau soit utilisable, le service a démarré immédiatement, tenté de résoudre un nom, échoué et est sorti. systemd l’a redémarré avec diligence.
La machine n’était pas « down », mais elle était dans une boucle de redémarrage pendant plusieurs minutes — parfois plus selon la congestion réseau.

Le pire : c’était intermittent. Si le DHCP était rapide, ça marchait. Sinon, non. L’équipe a goûté l’expérience classique d’entreprise :
un problème qui apparaît après que vous avez proclamé victoire.

Ils ont fait marche arrière, mais pas en réactivant une attente blanket de 120 secondes. Ils ont rendu la dépendance précise :
les services qui nécessitaient vraiment le réseau utilisable utilisaient une attente ajustée avec un timeout plus court et une sélection d’interface meilleure ;
les services pouvant retenter plus tard ont cessé de tirer network-online.

L’optimisation est une taxe. Si vous ne la payez pas en conception, vous la payez en incidents.

3) La pratique ennuyeuse mais correcte qui a sauvé la mise : journaux persistants + notes de changement

Une équipe de services financiers exécutait Debian sur du bare metal avec root chiffré et quelques mounts auxiliaires. Ils avaient une vieille règle :
journaling persistant activé partout, et tout changement lié au stockage exigeait une note d’une ligne dans un journal de changement interne : « quoi changé, comment annuler. »
Ennuyeux. Légèrement pénible. Parfait.

Un lundi, un hôte a démarré en mode emergency après une maintenance du week-end. La console affichait « Dependency failed », mais l’ingénieur n’a pas eu à deviner.
Les logs du boot précédent étaient là. Le journal pointait une seule unité de mount en échec, et la ligne d’erreur incluait le chemin de device exact introuvable.

Le journal de changement indiquait qu’un nouveau LUN iSCSI avait été ajouté et une entrée de mount créée. La personne qui l’avait fait avait aussi écrit le rollback : « commenter la ligne fstab et redémarrer. »
En quelques minutes, l’hôte était de nouveau en ligne, et l’équipe a investigué le problème de découverte iSCSI en plein jour.

La pratique n’était pas glamour. Elle ne « scalait pas les opérations pilotées par IA ». Elle faisait mieux : elle rendait la prochaine panne peu coûteuse.

Erreurs courantes : symptômes → cause racine → correction

1) Symptom : « Dependency failed for Local File Systems » et mode emergency

Cause racine : Un mount requis depuis /etc/fstab a échoué (UUID/LABEL erroné, disque manquant, échec fsck, déverrouillage crypto manquant).

Correction : Identifiez le .mount en échec avec systemctl --failed. Corrigez fstab. Si non critique, ajoutez nofail et un timeout court.

2) Symptom : délai de démarrage 90–120 secondes, puis le système finit par démarrer

Cause racine : *-wait-online.service expire, généralement parce qu’il n’y a pas de carrier, mauvais VLAN, ou attente d’une interface qui ne devrait pas compter.

Correction : Vérifiez quel wait-online est actif (networkd vs NetworkManager). Réduisez le timeout, ajustez les interfaces requises, ou retirez la dépendance sur network-online.target.

3) Symptom : « Dependency failed for Remote File Systems »

Cause racine : Une unité de montage distante (NFS/SMB/iSCSI) a échoué. Peut-être DNS, réseau, identifiants, ou serveur indisponible.

Correction : Rendez les montages distants nofail + x-systemd.automount quand approprié ; assurez-vous que _netdev est utilisé ; validez la résolution de noms tôt dans le boot.

4) Symptom : « A start job is running for dev-disk-by… » puis timeout

Cause racine : systemd attend une unité device qui n’apparaît jamais. Souvent un UUID obsolète, un mapping multipath manquant, ou un pilote absent de l’initramfs.

Correction : Confirmez avec lsblk -f et dmesg. Mettez à jour les identifiants. Pour un stockage en early-boot, assurez-vous que l’initramfs contient les modules et configs nécessaires.

5) Symptom : l’amorçage échoue après l’ajout d’une entrée de filesystem ; le montage manuel fonctionne ensuite

Cause racine : Problème d’ordonnancement : le device devient disponible après la tentative de montage (ex. iSCSI ou udev retardé). Ou vous avez besoin de x-systemd.requires= sur un service spécifique.

Correction : Utilisez x-systemd.automount ou ajoutez des dépendances correctes ; évitez les hacks du type « sleep 10 » dans les unités.

6) Symptom : « Je l’ai réparé », mais au prochain reboot ça replante

Cause racine : Vous avez édité l’état runtime ou une unité générée, pas la source (ex. édité dans /run), ou vous avez oublié daemon-reload, ou l’initramfs contient encore l’ancienne config.

Correction : Éditez /etc/fstab et les drop-ins sous /etc/systemd/system. Exécutez systemctl daemon-reload. Si le chiffrement/initramfs est impliqué, reconstruisez l’initramfs.

7) Symptom : messages « Dependency failed » mais tout semble OK

Cause racine : Des unités optionnelles échouent (ex. un mount marqué requis par défaut), ou un service one-shot est mal configuré mais non critique.

Correction : Décidez si l’unité doit être requise. Convertissez Requires= en Wants= là où c’est sûr. Ajoutez nofail aux montages optionnels. Nettoyez les unités en échec pour réduire le bruit.

Listes de contrôle / plan étape par étape

Checklist A — Récupérer le système maintenant (les minutes comptent)

  1. Obtenez un shell (mode emergency, mode recovery, ou TTY console).
  2. Exécutez systemctl --failed et notez les .mount/.service en échec.
  3. Exécutez journalctl -b -p err --no-pager et trouvez la première erreur pertinente.
  4. Si un mount échoue et n’est pas critique : commentez la ligne dans /etc/fstab, exécutez systemctl daemon-reload, redémarrez.
  5. Si un mount est critique : confirmez la présence du device avec lsblk -f, corrigez UUID/LABEL, exécutez mount -a, puis poursuivez le démarrage.

Checklist B — Identifier « l’unité unique » qui bloque le démarrage (être précis)

  1. Exécutez systemd-analyze critical-chain et notez l’unité avec le temps le plus long.
  2. Confirmez qu’elle bloque réellement : vérifiez si elle est sur le chemin vers multi-user.target ou votre target par défaut.
  3. Inspectez-la : systemctl status UNIT.
  4. Tirez son journal : journalctl -u UNIT -b --no-pager.
  5. Cartographiez les dépendances directes : systemctl list-dependencies --all UNIT et --reverse pour la target qu’elle retarde.
  6. Arrêtez-vous quand vous trouvez la ressource manquante (device, réseau, identifiant, fichier de config). C’est la vraie cause racine.

Checklist C — Corriger proprement (pour que le prochain reboot ne répète pas)

  1. Pour les mounts : utilisez des identifiants stables (UUID/LABEL) et confirmez avec lsblk -f.
  2. Pour les montages distants : préférez x-systemd.automount et nofail sauf si la machine ne peut vraiment pas fonctionner sans eux.
  3. Pour network-online : ne l’exigez que si le service a réellement besoin de routes/DNS fonctionnels au démarrage.
  4. Fixez des timeouts sensés : courts pour les dépendances optionnelles, longs uniquement si justifiés.
  5. Activez le journaling persistant sur les serveurs ; conservez les preuves de boot.
  6. Testez avec systemd-analyze blame et un redémarrage contrôlé.

Checklist D — Prévenir la réapparition (la taxe SRE utile)

  1. Ajoutez un script de validation pré-redémarrage : confirmer que tous les UUID dans /etc/fstab existent.
  2. Standardisez les options de montage pour les disques de données optionnels (automount + timeout court).
  3. Utilisez des drop-in pour surcharger les unités plutôt que d’éditer les fichiers fournisseurs.
  4. Documentez les étapes de rollback pour les changements de stockage et réseau.
  5. Après toute migration de stockage, faites une répétition de redémarrage dans une fenêtre de maintenance.

FAQ

1) « Dependency failed » est-ce un problème noyau ?

Généralement non. C’est systemd qui signale qu’une unité n’a pas pu démarrer parce que quelque chose dont elle dépend a échoué. Les problèmes noyau se manifestent plutôt par des panics, erreurs de pilote, ou device root manquant.

2) Pourquoi ça mentionne local-fs.target au lieu de la vraie défaillance ?

Les targets agrègent d’autres unités. Quand une unité requise échoue, la target rapporte un échec de dépendance. La vraie défaillance est typiquement un .mount ou un .service spécifique.

3) Quelle est la façon la plus rapide de trouver le bloqueur ?

Combinez systemctl --failed avec systemd-analyze critical-chain, puis lisez le journal pour le suspect principal. Ne commencez pas par éditer des fichiers d’unité au hasard.

4) Pourquoi mon système attend-il 120 secondes pour le réseau ?

C’est le timeout par défaut dans beaucoup d’unités wait-online. C’est un choix de politique, pas une loi de la physique. Si vous n’avez pas besoin de « online », ne dépendez pas de lui ; si oui, ajustez-le.

5) Dois-je utiliser nofail dans /etc/fstab ?

Pour les montages optionnels, oui — surtout amovibles, distants, ou « agréables à avoir ». Pour les montages requis (root, données critiques d’application), non. Corrigez la dépendance à la place.

6) Qu’apporte x-systemd.automount ?

Il diffère le montage jusqu’au premier accès. Le boot n’est pas bloqué. Si la ressource est temporairement absente, le système démarre quand même et vous pouvez réparer à distance.

7) Mon montage fonctionne après le boot, mais échoue pendant le boot. Pourquoi ?

Ordonnancement. Le device ou le chemin réseau n’est pas prêt quand le montage est tenté. L’automount est souvent la solution la plus propre. Sinon, ajoutez des dépendances correctes — évitez les hacks « sleep ».

8) Comment savoir si j’utilise NetworkManager ou networkd ?

Vérifiez quel service est enabled et actif. Si NetworkManager gère les interfaces, le wait-online de networkd peut être hors de propos et expirer inutilement.

9) J’ai corrigé /etc/fstab mais systemd échoue encore de la même façon. Qu’ai-je loupé ?

Exécutez systemctl daemon-reload et retestez avec mount -a. Si l’échec implique l’initramfs (disques chiffrés ou devices early-boot), reconstruisez aussi l’initramfs.

10) Puis-je simplement masquer l’unité en échec ?

Vous pouvez, et parfois vous devriez — temporairement. Masquer est un contournement, pas une cure. C’est acceptable pour des unités non critiques pendant que vous restaurez la disponibilité et planifiez une vraie correction.

Étapes suivantes (que faire après avoir rétabli l’amorçage)

Une fois le système de nouveau en ligne, ne vous contentez pas de « ça démarre maintenant ». Capturez la cause racine tant qu’elle est fraîche :
identifiez l’unité unique qui a bloqué le démarrage, documentez pourquoi elle a bloqué, et décidez si elle doit jamais être autorisée à bloquer à nouveau.

  1. Consignez l’unité coupable et la dépendance en échec (UUID, interface, endpoint distant).
  2. Rendez les dépendances optionnelles vraiment optionnelles : nofail, automount, timeouts courts pour devices.
  3. Rendez les dépendances requises fiables : identifiants corrects, ordonnancement correct, contenu initramfs correct.
  4. Activez le journaling persistant si ce n’est pas fait ; le prochain incident coûtera moins cher.
  5. Redémarrez une fois dans une fenêtre contrôlée pour valider la correction. La confiance se gagne, elle ne se présume pas.

Debian démarre bien. C’est votre configuration qui en fait un drame judiciaire. systemd n’est que le greffier qui énonce les conséquences.

← Précédent
Pourquoi les CPU chauffent : turbo, limites de puissance et réalité
Suivant →
Migration e-mail : déplacer la messagerie vers un nouveau serveur avec un temps d’arrêt minimal (étapes réelles)

Laisser un commentaire