Apprenez à éviter les erreurs courantes de configuration systemd, à valider les fichiers d’unité avant de les recharger, à effectuer des retours arrière sécurisés en cas d’échec et à dépanner les services à l’aide d’exemples pratiques et de commandes.
Introduction
systemd est le système d’initialisation et le gestionnaire de services par défaut sur la plupart des distributions Linux modernes. Il utilise des fichiers d’unité pour définir les services, les sockets, les minuteurs, les montages et d’autres ressources. Une simple directive mal placée, un chemin incorrect ou une dépendance manquante peut empêcher un service critique de démarrer, provoquer des échecs de démarrage ou créer des problèmes subtils au moment de l’exécution. Ce guide aide les ingénieurs à reconnaître les erreurs de configuration systemd courantes, à valider les modifications avant de les appliquer et à récupérer rapidement en cas de problème. Nous travaillerons avec un exemple concret : le durcissement d’un service Nginx existant. En chemin, nous passerons en revue le flux de travail de modification sécurisé, les commandes de diagnostic, les modes de défaillance et une liste de contrôle reproductible appartenant à un propriétaire de service désigné.
Inventaire des versions et de l’environnement
Avant de modifier une configuration systemd, établissez la version et les chemins de chargement sur le système cible. Cette base de référence détermine les directives disponibles et l’emplacement des fichiers.
Vérifiez la version de systemd :
systemctl --version
La sortie attendue affiche la version et les fonctionnalités de systemd :
systemd 249 (249.11-0ubuntu3.12)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FSTAB +IDN2 +IDN -KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE -BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified
Listez les chemins de chargement des fichiers d’unité :
systemd-analyze unit-paths
La sortie typique comprend :
/etc/systemd/system.control
/run/systemd/system.control
/run/systemd/transient
/run/systemd/generator.early
/etc/systemd/system
/etc/systemd/system.attached
/run/systemd/system
/run/systemd/system.attached
/run/systemd/generator
/usr/local/lib/systemd/system
/usr/lib/systemd/system
/usr/lib/systemd/system.attached
/run/systemd/generator.late
Notez que /etc/systemd/system est destiné aux remplacements de l’administrateur local, tandis que /usr/lib/systemd/system est généralement utilisé pour les unités fournies par le fournisseur. Les modifications sous /etc/systemd/system remplacent les valeurs par défaut du fournisseur.
Pour l’exemple du service Nginx, identifiez le fichier d’unité actuel et son état :
systemctl status nginx.service --no-pager
La sortie saine attendue comprend :
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2024-01-01 10:00:00 UTC; 2h ago
Docs: man:nginx(8)
Main PID: 1234 (nginx)
Tasks: 5 (limit: 1152)
Memory: 10.5M
CGroup: /system.slice/nginx.service
Enregistrez le chemin chargé, l’état actif et le PID principal comme référence.
Chemin de configuration sécurisé
Évitez de modifier directement les fichiers d’unité du fournisseur. Utilisez plutôt le mécanisme de drop-in de systemd pour remplacer des paramètres spécifiques. Les drop-ins gardent les modifications isolées et faciles à examiner ou à supprimer.
Créez un répertoire de drop-in pour le service Nginx :
sudo mkdir -p /etc/systemd/system/nginx.service.d
Créez un fichier de drop-in pour ajouter des directives de durcissement :
sudo tee /etc/systemd/system/nginx.service.d/hardening.conf <<'EOF'
[Service]
# Exemple de durcissement : empêcher Nginx d’obtenir de nouveaux privilèges
NoNewPrivileges=true
# Restreindre les répertoires inscriptibles pour une meilleure sécurité
ReadWritePaths=/var/log/nginx /var/cache/nginx
EOF
Avant d’appliquer la modification, validez la syntaxe du fichier d’unité :
sudo systemd-analyze verify /etc/systemd/system/nginx.service.d/hardening.conf
Si le fichier est valide, la commande ne produit aucune sortie. Toute erreur est signalée avec le nom du fichier et le numéro de ligne.
Après validation, rechargez la configuration du gestionnaire systemd et redémarrez le service :
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
Pour confirmer la configuration effective de l’unité, y compris les drop-ins :
systemctl cat nginx.service
Cela affiche l’unité fusionnée. Par exemple :
# /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
...
# /etc/systemd/system/nginx.service.d/hardening.conf
[Service]
NoNewPrivileges=true
ReadWritePaths=/var/log/nginx /var/cache/nginx
Si une erreur est introduite dans le drop-in, le service peut ne pas redémarrer. La commande renverra une erreur et le service passera à l’état « échec ». Pour revenir en arrière, supprimez le fichier de drop-in et rechargez :
sudo rm /etc/systemd/system/nginx.service.d/hardening.conf
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
Cela restaure le comportement original de l’unité du fournisseur.
Vérification et diagnostics
Après avoir modifié la configuration, vérifiez que le service a démarré correctement et que les directives prévues sont actives.
Vérifiez l’état du service :
systemctl status nginx.service --no-pager
Recherchez Active: active (running) et aucun message d’erreur.
Confirmez la valeur effective d’une propriété spécifique :
systemctl show nginx.service -p NoNewPrivileges -p ReadWritePaths
Sortie attendue :
NoNewPrivileges=yes
ReadWritePaths=/var/log/nginx /var/cache/nginx
Si le service a échoué, inspectez les journaux récents :
journalctl -u nginx.service -n 50 --no-pager
Cela affiche les erreurs de démarrage, telles que des directives non valides ou des chemins manquants.
Pour tester des modifications sans vous engager dans une configuration permanente, utilisez systemd-run pour créer une unité transitoire avec les paramètres candidats :
sudo systemd-run --unit=nginx-test --no-block --property=NoNewPrivileges=true --property=ReadWritePaths=/var/log/nginx /usr/sbin/nginx -g 'daemon off;'
Cela lance une instance Nginx temporaire avec le durcissement proposé. Vérifiez son état puis arrêtez-la :
systemctl status nginx-test.service --no-pager
sudo systemctl stop nginx-test.service
Cette approche permet d’expérimenter sans affecter le service principal.
systemd-analyze peut également vérifier les graphiques de dépendances des unités et les performances de démarrage, mais pour la vérification d’une unité individuelle, systemd-analyze verify est le plus pertinent.
Pièges courants et comment les éviter
Comprendre les erreurs fréquentes aide à les prévenir. Voici des pièges observés dans des déploiements réels, leurs causes et les stratégies d’évitement.
Modification directe des fichiers d’unité du fournisseur
Pourquoi cela arrive : Les administrateurs peuvent modifier /usr/lib/systemd/system/nginx.service parce que c’est le fichier affiché par systemctl cat. Les mises à jour de paquets écrasent ces modifications, provoquant une dérive de configuration et un comportement inattendu.
Comment l’éviter : Utilisez toujours des drop-ins sous /etc/systemd/system/nginx.service.d/. Le drop-in remplace des paramètres spécifiques tout en préservant le fichier du fournisseur. Examinez les modifications avec systemctl cat nginx.service pour voir le résultat fusionné.
Récupération : Si un fichier du fournisseur a été modifié, restaurez-le à partir du gestionnaire de paquets. Sur Debian/Ubuntu, exécutez sudo apt-get --reinstall install nginx. Sur RHEL/CentOS, exécutez sudo yum reinstall nginx puis réappliquez les modifications via des drop-ins.
Oublier d’exécuter daemon-reload avant de redémarrer
Pourquoi cela arrive : Après avoir créé ou modifié un fichier d’unité, les administrateurs peuvent directement exécuter systemctl restart sans recharger le gestionnaire systemd. Le gestionnaire peut ne pas prendre en compte la nouvelle configuration, ce qui entraîne l’ancien comportement ou une erreur du type « Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. Run 'systemctl daemon-reload' to reload units. »
Comment l’éviter : Prenez l’habitude d’exécuter sudo systemctl daemon-reload immédiatement après toute modification de fichier d’unité. Incluez cette commande dans les scripts d’automatisation et les listes de contrôle.
Récupération : Exécutez sudo systemctl daemon-reload puis redémarrez à nouveau le service.
Chemin incorrect dans ReadWritePaths ou ExecStart
Pourquoi cela arrive : Fautes de frappe ou hypothèses sur les emplacements de fichiers. Par exemple, spécifier /var/log/ngnx au lieu de /var/log/nginx ou supposer que le binaire est à /usr/local/nginx/sbin/nginx alors qu’il est en réalité à /usr/sbin/nginx.
Comment l’éviter : Vérifiez les chemins avant utilisation. Utilisez which nginx ou command -v nginx pour trouver l’exécutable. Vérifiez l’existence du répertoire avec ls -ld /var/log/nginx.
Récupération : Corrigez le fichier d’unité ou le drop-in, puis exécutez daemon-reload et redémarrez. Le service peut échouer avec un message du type Failed to execute /usr/sbin/nginx: No such file or directory.
Déclarations de dépendances manquantes
Pourquoi cela arrive : Les services nécessitent souvent que le réseau soit prêt ou qu’une autre unité soit démarrée en premier. Sans After=network.target et Wants=network.target, un service peut démarrer avant que le réseau ne soit disponible et échouer à se lier à un port. Un autre problème courant est de dépendre d’un montage qui n’est pas encore disponible.
Comment l’éviter : Déclarez explicitement les dépendances dans le fichier d’unité. Pour un serveur web, incluez :
[Unit]
After=network.target
Wants=network.target
Utilisez systemctl list-dependencies nginx.service pour visualiser les dépendances et vous assurer qu’elles correspondent aux attentes.
Récupération : Ajoutez la dépendance manquante et redémarrez. Si une unité de dépendance est introuvable, installez le paquet requis ou créez l’unité.
Ignorer la sortie de systemd-analyze verify
Pourquoi cela arrive : Les administrateurs peuvent sauter la validation pour gagner du temps, ce qui conduit à des erreurs de syntaxe qui ne se manifestent que lorsque le service ne démarre pas.
Comment l’éviter : Exécutez toujours systemd-analyze verify sur le fichier modifié ou l’unité complète avant de recharger. Traitez tout avertissement comme une erreur jusqu’à ce qu’il soit compris.
Récupération : Corrigez les erreurs signalées, relancez la vérification, puis rechargez et redémarrez.
Négliger l’inspection des journaux après un échec de démarrage
Pourquoi cela arrive : Après un redémarrage, le service peut afficher active (running) mais comporter encore des erreurs dans les journaux. Les administrateurs peuvent supposer le succès sans vérifier.
Comment l’éviter : Après le redémarrage, exécutez toujours journalctl -u nginx.service -n 50 --no-pager et recherchez les messages d’erreur ou d’avertissement. Portez attention aux lignes marquées emerg, alert, crit ou err.
Récupération : Si des erreurs sont trouvées, corrigez la cause première et redémarrez à nouveau.
Modes de défaillance et récupération
Les erreurs courantes comprennent les erreurs de syntaxe, les dépendances manquantes, les chemins incorrects et les types d’unité erronés. Voici des scénarios et les étapes de récupération.
Erreur de syntaxe dans le fichier d’unité
Si un drop-in contient une directive inconnue ou une syntaxe malformée, systemd-analyze verify la détectera avant le rechargement. Si vous contournez la vérification et exécutez systemctl daemon-reload, l’unité peut ne pas se charger. Pour récupérer, corrigez ou supprimez le fichier erroné, puis exécutez à nouveau daemon-reload.
Dépendance manquante
Si un service nécessite une autre unité qui n’est pas présente, il échouera à démarrer avec une erreur du type Failed to start nginx.service: Unit network-online.target not found. Dans ce cas, vous devrez peut-être installer un paquet ou créer l’unité manquante. Pour Nginx, assurez-vous que network.target est atteint ; ajoutez After=network.target dans l’unité si ce n’est pas déjà fait.
Chemin incorrect dans ReadWritePaths ou ExecStart
Si un chemin n’existe pas, le service peut échouer avec Failed to execute /usr/sbin/nginx: No such file or directory. Vérifiez le chemin réel de l’exécutable avec which nginx ou command -v nginx, et corrigez l’unité.
Retour arrière à l’aide du contrôle de version
Si vous gérez les fichiers d’unité dans un système de contrôle de version (par exemple, Git), vous pouvez rapidement revenir à une version connue comme bonne. Par exemple, si /etc/systemd/system est un dépôt Git, utilisez :
sudo git -C /etc/systemd/system checkout -- nginx.service.d/hardening.conf
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
Réparation de démarrage d’urgence
Si une erreur empêche le système de démarrer, utilisez le mode de récupération ou un CD live. Montez le système de fichiers racine, modifiez le fichier d’unité défectueux et redémarrez. Vous pouvez également utiliser la cible d’urgence de systemd : ajoutez systemd.unit=emergency.target à la ligne de commande du noyau au démarrage, puis corrigez l’unité et redémarrez normalement.
Persistance et masquage
Parfois, une unité ne doit démarrer sous aucune circonstance. Le masquage empêche les démarrages accidentels :
sudo systemctl mask nginx.service
Cela crée un lien symbolique vers /dev/null, remplaçant tous les fichiers d’unité. Pour démasquer :
sudo systemctl unmask nginx.service
Le masquage est une action de configuration délibérée, pas une erreur, mais oublier de démasquer peut prêter à confusion lorsqu’un service ne démarre pas.
Responsabilités et cadence de révision
Les modifications de configuration doivent avoir une propriété claire et des intervalles de révision pour maintenir la santé du système.
Propriétaire du service : Attribuez un unique propriétaire responsable pour chaque unité de service critique. Pour l’exemple Nginx, désignons Priya Shah, responsable de l’ingénierie, comme propriétaire. Elle est responsable de l’approbation et de la révision de toutes les modifications de la configuration de l’unité Nginx.
Fréquence de révision : La configuration de l’unité doit être révisée trimestriellement pour s’assurer que les directives de durcissement restent appropriées et que les chemins sont corrects. La prochaine date de révision est fixée au 15 juillet 2024. Cette révision comprend la vérification des nouvelles fonctionnalités de systemd, des dépréciations et des modifications de l’application.
Gestion des modifications : Toutes les modifications des fichiers d’unité doivent être relues par un pair avant d’être appliquées. Une demande de tirage ou une demande de fusion dans le système de contrôle de version sert de mécanisme de révision. Après l’application, la modification et son plan de retour arrière doivent être documentés dans le manuel d’exploitation.
Liste de contrôle des opérations
Utilisez cette liste de contrôle avant et après chaque modification de configuration systemd. Le propriétaire du service est responsable de s’assurer que chaque étape est suivie. La liste de contrôle doit être remplie pour chaque modification, et les résultats stockés avec l’enregistrement de la modification.
| Étape | Action | Commande ou vérification | Propriétaire |
|---|---|---|---|
| 1 | Confirmer la version de systemd | systemctl --version | Priya Shah |
| 2 | Noter le chemin de chargement actuel de l’unité | systemctl status <unit> --no-pager | Priya Shah |
| 3 | Sauvegarder l’unité ou le drop-in existant | Copier le fichier avec horodatage | Priya Shah |
| 4 | Effectuer les modifications dans un drop-in sous /etc/systemd/system/<unit>.d/ | Créer <setting>.conf | Priya Shah |
| 5 | Valider la syntaxe | systemd-analyze verify <file> | Priya Shah |
| 6 | Recharger la configuration du gestionnaire | sudo systemctl daemon-reload | Priya Shah |
| 7 | Redémarrer le service | sudo systemctl restart <unit> | Priya Shah |
| 8 | Vérifier l’état actif | systemctl status <unit> --no-pager | Priya Shah |
| 9 | Inspecter les propriétés effectives | systemctl show <unit> -p <Property> | Priya Shah |
| 10 | Vérifier les journaux pour les erreurs | journalctl -u <unit> -n 50 --no-pager | Priya Shah |
| 11 | En cas d’échec, retour arrière | Supprimer le drop-in ou restaurer la sauvegarde, puis recharger et redémarrer | Priya Shah |
| 12 | Documenter la modification et le plan de retour arrière | Mettre à jour le manuel d’exploitation | Priya Shah |
Cette liste de contrôle garantit une gestion de configuration cohérente et récupérable. Chaque étape appartient au propriétaire de service désigné, et la sortie est examinée lors de la révision trimestrielle de configuration.
Conclusion
Les erreurs de configuration systemd sont courantes mais évitables avec un flux de travail discipliné. Inventoriez toujours l’environnement, utilisez des remplacements de drop-in, validez avant de recharger, vérifiez après le redémarrage et ayez un plan de retour arrière. Dans ce guide, nous avons durci un service Nginx comme exemple concret, en montrant comment ajouter des directives en toute sécurité, tester avec une unité transitoire et récupérer après un échec. En suivant la liste de contrôle des opérations avec une propriété claire et une cadence de révision, les équipes peuvent réduire les interruptions de service et maintenir des systèmes Linux fiables. Commencez par une modification étroite, mesurez son effet et étendez-la avec confiance.