Vous essayez de redémarrer un service sur Debian 13 et systemd vous répond par l’équivalent opérationnel d’une porte verrouillée : « Unit is masked. » Pas de redémarrage, pas d’état exploitable, et votre fenêtre de changement fond sous vos yeux.
L’instinct est de le démasquer et d’avancer. Parfois c’est acceptable. Parfois c’est ainsi que vous réactivez accidentellement un service qui avait été désactivé pour des raisons de sécurité, d’intégrité ou de bon démarrage. Le but de cet article est de vous remettre en état de fonctionnement et d’éviter la prochaine surprise, car « unit masked » n’est que rarement toute l’histoire.
Ce que « masked » signifie réellement (et ce que ce n’est pas)
En termes systemd, une unité masquée est une unité rendue délibérément inémarrable. Pas « désactivée ». Pas « arrêtée ». Inémarrable. systemd met en œuvre le masquage en plaçant un lien symbolique portant le nom du fichier d’unité (ou son drop-in) qui pointe vers /dev/null. C’est un véto net : pas de démarrage manuel, pas de démarrage par dépendance, pas d’activation accidentelle.
Le masquage est utilisé pour quelques raisons légitimes :
- Empêcher un service problématique de démarrer via des dépendances ou des sockets.
- Éviter qu’un service legacy soit automatiquement tiré par d’autres unités.
- Empêcher un administrateur de « juste essayer de le lancer » en situation de panique.
- Outrepasser des unités fournies par le fournisseur quand le paquet n’offre pas de réglage propre.
Et il est utilisé pour quelques raisons illégitimes :
- Des scripts d’automatisation utilisent
maskcomme un outil brut et ne nettoient jamais après. - Quelqu’un masque une unité pendant un incident et oublie de le documenter.
- Une image cloud est distribuée avec des services masqués pour éviter des surprises au démarrage, puis vous attendez que ces services fonctionnent.
Le masquage n’est pas la même chose que :
- Désactivé : ne démarre pas au démarrage, mais peut être démarré manuellement (
systemctl startfonctionne). - Statique : ne peut pas être activé (
[Install]absent) mais peut démarrer via des dépendances. - En échec : démarré puis planté, ou jamais démarré en raison d’erreurs à l’exécution.
- Introuvable : le fichier d’unité n’existe pas (ou le générateur ne l’a pas créé).
Le masquage est une décision de politique. Votre travail est de comprendre pourquoi cette décision de politique a été prise, et si elle doit rester en place.
Playbook de diagnostic rapide (vérifier premièrement/deuxièmement/troisièmement)
Premier : confirmer l’état de l’unité et où le masquage est appliqué
- Est-ce masqué à l’exécution, ou via un lien persistant ?
- Est-ce masqué dans l’instance système ou dans l’instance utilisateur ?
- S’agit-il de l’unité elle-même, ou d’un alias/template/socket qui est masqué ?
Second : trouver qui/quoi a demandé le masquage
- Consultez les scripts de paquet (logs dpkg), les logs de gestion de configuration et l’historique shell si pertinent.
- Vérifiez si un méta-paquet ou une politique de preset force un état inattendu.
- Recherchez des drop-ins qui entrent en conflit avec le chemin d’activation de l’unité.
Troisième : décider si démasquer est sans risque
- Le démarrage de ce service entraîne-t-il un risque de perte de données (montages, chiffrement, réplication) ?
- Ouvre-t-il des écouteurs réseau indésirables (par ex. démons de debug) ?
- S’opposera-t-il à un autre service (deux clients DHCP, deux services de synchronisation horaire, deux firewalls) ?
Ce n’est qu’après cela que vous démasquez. « Démasquer d’abord, demander après » transforme une simple panne en postmortem.
Tâches pratiques : commandes, sorties, décisions (12+)
Voici les actions exactes que j’utilise en production. Chaque tâche inclut une commande, une sortie réaliste et la décision qui en découle.
Task 1: Reproduce the failure and capture the exact error
cr0x@server:~$ sudo systemctl start fstrim.timer
Failed to start fstrim.timer: Unit fstrim.timer is masked.
Ce que cela signifie : systemd a refusé avant même d’évaluer les dépendances. C’est du niveau politique, pas d’exécution.
Décision : Ne pas « juste démasquer » tout de suite. Identifiez où le masque se trouve et si c’est intentionnel.
Task 2: Check status (it tells you how systemd sees it)
cr0x@server:~$ systemctl status fstrim.timer
○ fstrim.timer
Loaded: masked (Reason: Unit fstrim.timer is masked.)
Active: inactive (dead)
Ce que cela signifie : « Loaded: masked » confirme que la définition d’unité est surchargée vers /dev/null (ou équivalent).
Décision : Suivant : localiser le lien symbolique et déterminer s’il est system-wide ou un masque transitoire.
Task 3: Find the unit file path (or the fact it’s /dev/null)
cr0x@server:~$ systemctl show -p FragmentPath -p UnitFileState fstrim.timer
FragmentPath=/etc/systemd/system/fstrim.timer
UnitFileState=masked
Ce que cela signifie : Le masque est dans /etc, pas dans un fichier fournisseur sous /lib. Quelqu’un (humain ou automatisation) a fait cela exprès.
Décision : Inspecter le fichier pour confirmer qu’il s’agit d’un lien symbolique vers /dev/null.
Task 4: Verify the mask symlink target
cr0x@server:~$ ls -l /etc/systemd/system/fstrim.timer
lrwxrwxrwx 1 root root 9 Dec 29 03:12 /etc/systemd/system/fstrim.timer -> /dev/null
Ce que cela signifie : Masque classique. Pas d’ambiguïté.
Décision : Déterminez qui l’a créé et si vous souhaitez réellement que fstrim.timer s’exécute sur cette classe d’hôtes (VM ? SSD ? SAN thin-provisioned ?).
Task 5: Check if this is a runtime mask instead (less common, but sneaky)
cr0x@server:~$ systemctl show -p FragmentPath fstrim.timer
FragmentPath=/etc/systemd/system/fstrim.timer
Ce que cela signifie : Pas transitoire. S’il s’agissait d’un masque runtime, on verrait souvent un masquage sous /run/systemd/system.
Décision : Passer aux pistes d’audit : logs dpkg, gestion de config, ou actions administrateur.
Task 6: Confirm whether the vendor unit exists (it matters when unmasking)
cr0x@server:~$ systemctl cat fstrim.timer
# /etc/systemd/system/fstrim.timer
# (null)
Ce que cela signifie : systemd charge littéralement « rien » parce que le fichier est /dev/null. Vous devez savoir quel fichier devrait être utilisé à la place.
Décision : Vérifier l’unité fournie par le fournisseur dans /lib/systemd/system et si elle est installée.
Task 7: Locate the vendor unit and its install behavior
cr0x@server:~$ ls -l /lib/systemd/system/fstrim.timer
-rw-r--r-- 1 root root 402 Jan 5 10:02 /lib/systemd/system/fstrim.timer
Ce que cela signifie : L’unité existe et peut être restaurée en démasquant (systemd retombera sur l’unité fournisseur).
Décision : Avant de démasquer, évaluez s’il faut activer pour l’amorçage, ou seulement démarrer manuellement.
Task 8: Check if the unit is enabled/disabled after unmasking (don’t assume)
cr0x@server:~$ systemctl is-enabled fstrim.timer
masked
Ce que cela signifie : C’est masqué, donc l’état d’activation est sans objet tant que le masque reste.
Décision : Plan : démasquer, puis décider entre enable et start.
Task 9: Unmask safely (unit only, no surprise restarts)
cr0x@server:~$ sudo systemctl unmask fstrim.timer
Removed "/etc/systemd/system/fstrim.timer".
Ce que cela signifie : Le lien symbolique a été supprimé. Cela ne signifie pas que l’unité est activée ou démarrée.
Décision : Rechargez le démon si vous modifiez des fichiers d’unité en masse ; pour un simple démasquage ce n’est généralement pas nécessaire, mais je vérifie toujours l’état immédiatement.
Task 10: Verify the unit is now loadable, and see its default state
cr0x@server:~$ systemctl show -p FragmentPath -p UnitFileState fstrim.timer
FragmentPath=/lib/systemd/system/fstrim.timer
UnitFileState=disabled
Ce que cela signifie : Maintenant systemd utilise l’unité fournisseur et elle est désactivée (ne démarre pas au boot).
Décision : Décidez si vous devez l’activer. Pour un timer comme fstrim, on l’active presque toujours, mais vérifiez d’abord le stockage et la politique.
Task 11: Enable (for boot persistence) or start (for immediate use)
cr0x@server:~$ sudo systemctl enable --now fstrim.timer
Created symlink '/etc/systemd/system/timers.target.wants/fstrim.timer' → '/lib/systemd/system/fstrim.timer'.
Ce que cela signifie : Il s’exécutera selon le calendrier et est démarré maintenant. Les timers sont une classe relativement sûre à activer, mais vérifiez le comportement.
Décision : Confirmez qu’il est actif et vérifiez la prochaine activation.
Task 12: Confirm timer schedule and last/next runs
cr0x@server:~$ systemctl list-timers --all | sed -n '1,6p'
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2025-12-30 03:15:00 UTC 2h 11min left Mon 2025-12-29 03:15:01 UTC 21h ago fstrim.timer fstrim.service
Ce que cela signifie : Vous êtes revenu à un calendrier prévisible. Si « LAST » est vide, il se peut qu’il ne se soit pas encore exécuté.
Décision : Si ce timer doit se déclencher hebdomadairement mais que votre équipe stockage refuse DISCARD, arrêtez ici et coordonnez-vous.
Task 13: Identify whether a related unit is masked instead (socket, path, template)
cr0x@server:~$ systemctl list-unit-files | grep -E '^(ssh|ssh@|ssh\.socket)'
ssh.service enabled
ssh.socket masked
ssh@.service static
Ce que cela signifie : Vous essayez peut-être de démarrer un service normalement déclenché par un socket. Si le socket est masqué, l’activation n’aura jamais lieu.
Décision : Décidez si vous voulez l’activation par socket. Démasquer le socket peut avoir des conséquences de sécurité (apparition d’écouteurs).
Task 14: Follow the dependency chain to see who would pull it in
cr0x@server:~$ systemctl list-dependencies --reverse fstrim.service | head
fstrim.service
● multi-user.target
Ce que cela signifie : Si les dépendances inverses incluent des targets de haut niveau, l’activation peut modifier le comportement de démarrage.
Décision : Si elle est largement tirée, assurez-vous qu’elle ne bloquera pas le démarrage (problèmes d’ordre stockage/réseau).
Task 15: Inspect dpkg logs for package scripts that might have masked something
cr0x@server:~$ grep -n "mask" /var/log/dpkg.log | tail -n 5
23341:2025-12-29 03:11:52 status installed util-linux:amd64 2.40.2-1
23342:2025-12-29 03:12:03 configure util-linux:amd64 2.40.2-1 <none>
Ce que cela signifie : dpkg lui-même n’enregistre pas le masquage comme « mask » ; la plupart des masquages viennent d’appels systemctl dans des scripts des mainteneurs ou de la gestion de configuration. L’absence de preuve n’est pas preuve d’absence.
Décision : Si vous suspectez un script de paquet, inspectez les scripts des mainteneurs sur le disque.
Task 16: Check maintainer scripts for unit manipulation (where masking can be hidden)
cr0x@server:~$ dpkg -L util-linux | grep -E '/(postinst|prerm|postrm)$'
/var/lib/dpkg/info/util-linux.postinst
/var/lib/dpkg/info/util-linux.prerm
/var/lib/dpkg/info/util-linux.postrm
cr0x@server:~$ sudo grep -n "systemctl .*mask" /var/lib/dpkg/info/util-linux.postinst
Ce que cela signifie : Aucun masquage explicite dans ce script (dans cet exemple). Bon à vérifier quand un masque apparaît juste après une mise à jour.
Décision : Si les scripts sont propres, concentrez-vous sur l’automatisation, cloud-init et l’action humaine.
Task 17: Audit who ran systemctl (best-effort)
cr0x@server:~$ sudo journalctl -u systemd-logind --since "2025-12-29" | head -n 6
Dec 29 03:09:18 server systemd-logind[610]: New session 42 of user root.
Dec 29 03:09:18 server systemd-logind[610]: Removed session 41.
Dec 29 03:12:01 server systemd-logind[610]: Session 42 logged out. Waiting for processes to exit.
Ce que cela signifie : Ce n’est pas une piste d’audit parfaite, mais ça peut corréler des sessions avec l’heure où le lien de masque est apparu (à partir des timestamps du système de fichiers ou des diff de sauvegarde).
Décision : Si vous avez besoin d’un suivi réel, déployez des règles auditd pour les changements de /etc/systemd/system. Sinon, considérez cela comme un indice, pas une preuve.
Pourquoi des unités sont masquées sur Debian 13 (raisons réelles)
« C’est masqué » est le symptôme. Les causes racines ont tendance à se regrouper. Si vous apprenez ces regroupements, vous arrêtez d’être surpris.
1) Un humain l’a masqué pour arrêter une boucle de démarrage ou un incident
Cela arrive souvent avec les services réseau (dhcpcd vs NetworkManager), les services de stockage (multipath, iscsid), et tout ce qui peut bloquer le démarrage (remote-fs.target). Le masquage est l’option nucléaire utilisée à 03:00 quand « disable » n’a pas empêché l’activation via des dépendances.
2) La gestion de configuration a utilisé le masquage comme « off » idempotent
Certaines playbooks traitent « masked » comme une version plus stricte de disabled. Ce n’est pas faux. C’est juste un engagement plus fort que beaucoup d’équipes ne réalisent pas. La surprise survient plus tard quand un rôle s’attend à ce que l’unité démarre et que vous obtenez un refus net.
3) Une image cloud ou appliance a été fournie avec des unités masquées
Les builders d’images masquent des services pour éviter des démarrages lents, des logs bruyants ou des defaults non sécurisés. Les images basées sur Debian en particulier peuvent livrer certains timers ou services désactivés/masqués pour garder l’image de base générique. Quand vous installez plus tard un paquet qui attend que le service démarre, vous obtenez « masked » et le mainteneur du paquet se fait blâmer pour la politique d’image.
4) Le fournisseur a masqué l’unité pour forcer une migration
Parfois un service est déprécié et masqué pour empêcher son démarrage accidentel. C’est moins fréquent dans Debian que chez certains fournisseurs, mais ça arrive lors de transitions (par ex. quand un service est remplacé par une version activée par socket, ou quand un ancien démon est dangereux).
5) Vous avez masqué la mauvaise chose (alias, socket, template)
Les unités systemd viennent en familles : .service, .socket, .timer, .path, et des templates comme foo@.service. Masquer l’un peut donner l’impression que toute la fonctionnalité est morte. J’ai vu des gens démasquer le service mais laisser le socket masqué puis jurer que systemd les « ignore ». Ce n’est pas le cas. Il obéit à votre décision précédente.
6) Une unité est générée, et vous avez masqué le nom généré
Certaines unités sont générées au démarrage par des generators systemd (par exemple, à partir d’entrées fstab). Si vous masquez un nom d’unité généré, vous pouvez le maintenir hors service. Mais si le générateur change le nom (ou si vous passez de chemins de périphérique à des UUID), votre masque cesse de correspondre et le montage reprend. Ce n’est pas systemd qui est « aléatoire » ; c’est vous qui avez épinglé une politique sur un identifiant instable.
Une citation que je garde dans un coin de la tête :
Werner Vogels : « Everything fails, all the time. » (idée paraphrasée)
Le masquage est un des mécanismes que nous utilisons pour rendre les échecs prévisibles. Quand il est accidentel, il fait le contraire.
Démasquer en sécurité : la séquence correcte et les pièges
Voici la posture sûre : traitez le démasquage comme vous traiteriez l’activation d’une règle firewall ou le remontage d’un système de fichiers. Vous pouvez le faire rapidement, mais consciemment.
Étape 1 : Identifiez exactement ce qui est masqué
Ne supposez pas qu’il s’agit du .service. Cela peut être le timer qui doit le déclencher, le socket qui doit l’activer, ou un alias que vous tapez par habitude.
Étape 2 : Identifiez où le masque est défini
S’il est dans /etc/systemd/system, c’est une politique locale. S’il est dans /run/systemd/system, il peut être transitoire. S’il est dans /lib/systemd/system (rare pour un masquage), c’est une politique fournisseur.
Étape 3 : Décidez si vous le voulez activé à long terme
Le démasquage enlève seulement l’interdiction de démarrer. Il n’active pas. Ne lancez pas réflexivement enable --now à moins d’être sûr que l’unité doit fonctionner au démarrage. Pour une récupération ponctuelle, préférez unmask + start seulement.
Étape 4 : Attention à l’effet « démarre autre chose »
Démasquer un socket ou une unité path peut immédiatement changer la façon dont les requêtes sont acceptées. Démasquer un timer peut le faire commencer à se déclencher en fonction des timers persistants (exécutions manquées). C’est une fonctionnalité, mais cela surprend.
Petite blague #1 : le masquage systemd, c’est comme coller un panneau « NE PAS OUVRIR » sur une porte — puis être étonné qu’elle ne s’ouvre pas.
Étape 5 : Si l’unité était masquée pour une raison, corrigez la raison
Le masquage est rarement la vraie solution. C’est le garrot. Il faut soigner la blessure : démons conflictuels, config cassée, dépendances foireuses, ou inadéquation d’environnement (conteneurs, chroots, images minimales).
Faits et historique intéressants qui expliquent le comportement actuel
- Fait 1 : le masquage systemd est principalement implémenté via un lien symbolique vers
/dev/null, qui écrase presque toutes les autres sources d’unité dans l’ordre de recherche. - Fait 2 : l’intégration systemd de Debian s’appuie fortement sur le mécanisme de « vendor preset » : les paquets peuvent proposer des états d’activation suggérés, mais les admins locaux peuvent surcharger.
- Fait 3 : la distinction entre disabled et masked est intentionnelle : disabled empêche l’activation au démarrage ; masked empêche toute activation, y compris via des dépendances.
- Fait 4 : l’ordre de recherche des unités systemd privilégie
/etc/systemd/systemavant/runavant/lib/systemd/system. C’est pourquoi le masquage local sous/etcest si décisif. - Fait 5 : une unité peut être « statique » et démarrer automatiquement via des dépendances ; beaucoup d’admins rencontrent « statique » la première fois qu’ils essaient d’
enablequelque chose qui n’était pas censé être activé directement. - Fait 6 : les timers ont remplacé beaucoup de jobs cron anciens dans les distributions modernes, et certaines images masquent les timers pour réduire le bruit en arrière-plan sur des instances légères.
- Fait 7 : l’activation par socket signifie que le
.socketpeut être plus important que le.service; masquer le socket équivaut à masquer la fonctionnalité. - Fait 8 : aux débuts de l’adoption de systemd, « mask it » est devenu un contournement courant pour empêcher les services SysV-compat de respawn à cause de scripts init legacy ou de dépendances.
- Fait 9 : le masquage est réversible sans réinstaller les paquets, ce qui explique son usage opérationnel pendant les incidents — rapide, déterministe et brutal.
Trois mini-récits d’entreprise tirés du terrain
Mini-récit 1 : La panne causée par une mauvaise hypothèse
Une enseigne de distribution utilisait Debian sur des passerelles edge en magasin. Les passerelles utilisaient un service VPN avec une unité systemd. Lors d’une migration, un ingénieur senior a décidé « on va désactiver temporairement l’unité VPN legacy pour tester la nouvelle ». Ils ont utilisé systemctl mask parce que cela empêchait l’unité de démarrer immédiatement et empêchait aussi l’ancien service d’être tiré par d’autres unités.
L’hypothèse : le masquage se comporte comme un disable renforcé et sera retiré plus tard par le rôle de migration. La réalité : le rôle de migration appelait seulement disable/enable, jamais unmask. Il ne vérifiait même pas l’état masqué. Le playbook était « correct » au sens étroit, mais aveugle au marteau politique utilisé plus tôt.
Des semaines plus tard, un correctif de sécurité nécessitait le redémarrage du VPN. Le déploiement a buté sur les unités masquées en premier (à cause d’un mauvais ordre). L’orchestrateur a interprété « failed to start » comme une erreur fatale et a interrompu le processus. Les magasins se sont retrouvés partiellement mis à jour : certains gateways avaient un noyau patché, d’autres non ; certains avaient le VPN, d’autres non.
La correction fut triviale — démasquer et redémarrer. La leçon ne l’était pas. Ils ont ajouté une vérification préliminaire : toute unité critique pour la connectivité doit être enabled ou disabled, jamais masked, sauf si l’enregistrement de changement le documente explicitement. Ils ont aussi mis à jour le rôle de migration pour traiter le masquage comme un état séparé nécessitant une gestion intentionnelle.
Mini-récit 2 : L’optimisation qui a mal tourné
Une entreprise média voulait des démarrages plus rapides sur ses nœuds de rendu Debian 13. Quelqu’un a remarqué une poignée d’unités attendant network-online et des montages distants. L’« optimisation » rapide a été de masquer des services qui semblaient optionnels : un démon de synchronisation horaire, un timer de trim, et un helper de montage distant. Le démarrage s’est accéléré. Tout le monde s’est félicité et est retourné à se chamailler sur les drivers GPU.
Le retour de bâton est arrivé silencieusement. La ferme de rendu utilisait des nœuds longue durée, et sans trim périodique les performances des SSD se sont dégradées lentement. Le démon de synchronisation horaire masqué a causé des échecs intermittents de validation de certificats après des redémarrages où l’horloge avait dérivé suffisamment. Le helper de montage distant masqué a fait basculer un chemin de secours : les jobs écrivaient des caches sur disques locaux plutôt que sur le stockage partagé.
Aucune de ces défaillances n’était spectaculaire. Elles étaient du pire genre : sporadiques, inter-équipes et difficiles à corréler. Le masquage était le dénominateur commun, mais il a fallu une semaine pour le remarquer parce que « masked » n’est pas un état de panne — c’est un état politique.
Ils ont annulé les masquages, puis fait le travail ennuyeux : corriger les dépendances d’ordre, réduire l’usage de network-online, et définir des timeouts sensés. Le démarrage est resté raisonnablement rapide, et la flotte a cessé d’accumuler une dette invisible.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une fintech utilisait Debian 13 pour des services internes. Ils avaient une habitude qui semblait bureaucratique : un job d’audit quotidien comparant /etc/systemd/system contre une baseline connue pour chaque rôle serveur. Ce n’était pas sophistiqué ; il signalait simplement les liens symboliques inattendus, en particulier ceux pointant vers /dev/null.
Un matin, l’audit a déclenché : un timer de sauvegarde de base de données était masqué sur une poignée d’hôtes. Personne n’avait ouvert d’incident. Pas d’alerte. Juste un diff. Ils ont enquêté avant que les sauvegardes ne soient manquées au point d’être problématiques.
Cause racine : un ingénieur junior a exécuté un script de « nettoyage » temporaire lors d’un événement de pression disque. Le script a masqué plusieurs timers pour arrêter le churn I/O, avec toute l’intention de les démasquer plus tard. Ils ont été détournés par une autre tâche et ont oublié. L’audit l’a trouvé le lendemain, avant que la conformité ne le remarque.
Ils ont démasqué le timer, lancé une sauvegarde à la demande, et ajouté un runbook : si vous masquez quelque chose comme mesure provisoire, créez un ticket qui expire et qui envoie une alerte si non résolu. La pratique était ennuyeuse. Elle a marché. L’ennui est sous-estimé en opérations.
Erreurs courantes : symptôme → cause racine → correction
1) « systemctl enable dit que l’unité est masquée »
Symptôme : Failed to enable unit: Unit file is masked
Cause racine : Vous essayez de changer l’état d’activation alors qu’une surcharge /dev/null existe.
Correction : systemctl unmask UNIT, puis relancez systemctl enable. Vérifiez que FragmentPath est passé de /etc à /lib ou à un override valide.
2) « Je l’ai démasqué mais il ne démarre toujours pas »
Symptôme : Service démasqué, mais activation encore échoue ou n’a jamais lieu.
Cause racine : L’unité déclencheuse est masquée (socket/timer/path) ou l’unité est statique et ne démarre que via des dépendances que vous ne satisfaîtes pas.
Correction : Vérifiez les unités liées : systemctl list-unit-files | grep NAME. Démasquez le déclencheur (si approprié) et validez les dépendances avec list-dependencies.
3) « C’est masqué à nouveau après le reboot »
Symptôme : Vous démasquez, mais l’unité se retrouve masquée plus tard.
Cause racine : L’automatisation (Ansible/Puppet/Salt), cloud-init, ou un rôle de durcissement réapplique le masque.
Correction : Trouvez et enlevez la politique. Greppez votre repo de configuration pour le nom de l’unité et pour systemctl mask. Si vous ne pouvez pas changer l’automatisation rapidement, ajoutez un override géré : imposer l’état unmasked en code.
4) « L’installation du paquet n’a pas démarré le service »
Symptôme : Vous installez un paquet et attendez que le service démarre ; il ne démarre pas et vous découvrez plus tard qu’il est masqué.
Cause racine : L’image hôte avait déjà l’unité masquée, ou la politique de preset l’a désactivée, et le postinst du paquet a respecté la politique admin.
Correction : Confirmez le preset fournisseur avec systemctl preset-status (là où disponible), et vérifiez les masques existants dans /etc/systemd/system. Décidez si vous suivez la politique d’image ou la surchargez pour ce rôle.
5) « Masquer pour corriger un crash »
Symptôme : Quelqu’un a masqué une unité pour empêcher qu’elle plante en boucle.
Cause racine : Le masquage est utilisé en lieu et place de la correction du crash ou de la mauvaise configuration.
Correction : Démasquez dans une fenêtre contrôlée, inspectez les logs (journalctl -u), corrigez la config, puis réactivez. Si vous devez la garder hors service, préférez disable sauf si l’activation par dépendance est un risque.
6) « Unités de montage masquées et bizarreries de stockage »
Symptôme : Les montages de stockage ne se produisent pas ; des services échouent en attendant des systèmes de fichiers.
Cause racine : Un mount unit généré à partir de fstab a été masqué pour éviter des blocages, mais le problème de stockage sous-jacent n’a jamais été résolu (DNS, iSCSI, multipath, credentials).
Correction : Corrigez la dépendance de stockage sous-jacente. Utilisez des timeouts raisonnables et nofail où approprié. Masquer des montages est acceptable comme mesure temporaire, pas comme architecture.
Petite blague #2 : Si votre « correctif » consiste à masquer des services, vous ne faites pas du SRE — vous jouez au whack-a-mole systemd.
Listes de contrôle / plan étape par étape
Checklist A: Récupération d’une unité (rapide, sûre)
- Capturez l’erreur :
systemctl start UNITet copiez le message exact. - Confirmez l’état :
systemctl status UNITetsystemctl is-enabled UNIT. - Localisez le masque :
systemctl show -p FragmentPath UNIT. - Vérifiez le lien :
ls -l FRAGMENTPATHet confirmez-> /dev/null. - Vérifiez l’unité fournisseur :
ls -l /lib/systemd/system/UNIT. - Évaluez la sécurité : le démarrage ouvre-t-il des ports, monte-t-il des stockages, modifie-t-il des disques, ou entre-t-il en conflit avec un autre démon ?
- Démasque :
systemctl unmask UNIT. - Vérifiez que FragmentPath est passé à un fichier réel.
- Démarrez (temporaire) ou
enable --now(persistant), explicitement. - Validez : logs (
journalctl -u UNIT -b), checks de santé, et timers/sockets pertinents.
Checklist B: Prévention à l’échelle de la flotte
- Inventaire des masques : trouvez les liens symboliques vers
/dev/nullsous/etc/systemd/system. - Classez : intentionnel (documenté) vs accidentel (origine inconnue).
- Pour les masques intentionnels, ajoutez un commentaire dans votre gestion de config et une référence de ticket dans votre runbook.
- Pour les masques accidentels, démasquez et corrigez la cause racine (conflits, ordre, configs cassées).
- Ajoutez des tests CI pour empêcher de nouveaux masques dans les rôles sauf approbation explicite.
- Détection de dérive de baseline : alertez sur les nouveaux
/etc/systemd/system/*.service -> /dev/null.
Task pack: fleet inventory commands (bonus, still practical)
cr0x@server:~$ sudo find /etc/systemd/system -maxdepth 2 -type l -lname /dev/null -printf '%p -> %l\n' | head
/etc/systemd/system/fstrim.timer -> /dev/null
/etc/systemd/system/ssh.socket -> /dev/null
Ce que cela signifie : Ce sont vos masques. Chaque ligne est une décision politique faite par quelqu’un.
Décision : Pour chacun, décidez : garder (documenter) ou supprimer (unmask + corriger la cause racine).
FAQ
1) Quelle est la différence entre disable et mask ?
disable supprime les liens qui démarrent l’unité au boot. L’unité peut toujours être démarrée manuellement ou comme dépendance. mask rend l’unité inémarrable dans n’importe quel scénario.
2) systemctl unmask démarre-t-il le service ?
Non. Il enlève seulement le veto. Il faut encore start pour activation immédiate et enable pour la persistance au démarrage.
3) Pourquoi l’unité masquée se trouve-t-elle dans /etc/systemd/system ?
Parce que le masquage est généralement une politique d’admin locale. systemd recherche /etc en premier, donc les overrides locaux l’emportent sur les valeurs par défaut du fournisseur.
4) Une unité peut-elle être masquée sans qu’un lien symbolique apparaisse dans /etc ?
Oui. Elle peut être masquée de façon transitoire dans /run/systemd/system, ou vous pouvez viser un nom d’unité différent (alias/socket/template) de celui que vous pensez.
5) Pourquoi le masquage serait-il intervenu pendant une mise à jour ?
Souvent, ce n’est pas la mise à jour qui a masqué. Les mises à jour révèlent une politique existante parce que les paquets changent des valeurs par défaut, ajoutent des timers, ou modifient des chemins d’activation. Si vous suspectez des scripts de mainteneur, inspectez /var/lib/dpkg/info/*.postinst pour des appels systemctl.
6) Si je démasque, Debian « se souviendra » et le gardera démasqué pendant les mises à jour ?
Oui, parce que le masque était un fichier dans /etc. Une fois retiré, il reste retiré — sauf si l’automatisation ou un rôle de durcissement le recrée.
7) Quelle est la façon la plus sûre de tester un démasquage en production ?
Démasquez sans activer, puis démarrez manuellement et surveillez les logs. Pour des écouteurs réseau, confirmez les sockets/ports avant et après. Pour des services liés au stockage, validez les montages et dépendances avant le redémarrage.
8) Puis-je masquer une unité pour empêcher qu’elle soit démarrée indirectement ?
Oui, c’est un cas d’utilisation valide. Si l’activation par dépendance est problématique et que disable n’est pas assez fort, le masquage est l’outil adapté — il suffit de le documenter et d’auditer la dérive.
9) Pourquoi systemctl cat affiche-t-il « (null) » ?
Parce que le fichier d’unité est littéralement /dev/null. systemd vous dit « j’ai chargé rien, par conception. » C’est le masque.
10) Comment éviter de masquer des montages puis d’oublier ?
Traitez les masques comme des mesures d’incident expirables. Créez un ticket, ajoutez une alerte sur les liens de masque, et corrigez le vrai problème (timeouts, ordre, credentials, readiness réseau).
Conclusion : prochaines étapes durables
Quand Debian 13 dit « Unit is masked », ce n’est pas mystérieux. C’est obéissant. Un masque est une surcharge politique délibérée, implémentée de la façon la plus simple possible : un lien symbolique vers nulle part.
Faites ce qui suit :
- Pour l’unité qui vous bloque : capturez
FragmentPath, vérifiez la cible du lien, et enregistrez où la politique vivait. - Démasque uniquement après avoir jugé que c’est sûr, puis choisissez intentionnellement entre
startetenable --now. - Trouvez l’auteur : automatisation, politique d’image, ou correctif humain d’un incident. Enlevez la surprise à la source.
- Hygiène de flotte : auditez
/etc/systemd/systempour les liens-> /dev/nullet traitez les masques non documentés comme des défauts.
Si vous ne retenez qu’une règle opérationnelle : démasquer corrige le symptôme ; comprendre pourquoi cela a été masqué corrige le système.