Server
Difficulte: Intermediate
14 min de lecture

systemd : Gestion complète des services Linux

Maîtrisez systemd de A à Z : gestion des services, création d'units, timers, journald, targets, sécurisation et debugging sur les systèmes Linux modernes.

Retour aux tutoriels
À propos de systemd
systemd est le système d'initialisation et le gestionnaire de services standard sur la majorité des distributions Linux modernes (Debian, Ubuntu, CentOS, Fedora, Arch). Il remplace les anciens systèmes init comme SysVinit et Upstart, en apportant un démarrage parallélisé, une gestion des dépendances et un écosystème complet d'outils d'administration.

Prérequis

  • Système d'exploitation : Distribution Linux utilisant systemd (Debian 8+, Ubuntu 15.04+, CentOS 7+, Fedora 15+)
  • Privilèges : Accès root ou privilèges sudo pour la gestion des services
  • Connaissances : Bases de l'administration Linux et du terminal
  • Version : systemd 245+ recommandé pour les fonctionnalités avancées

Vérifiez votre version de systemd :

systemctl --version
# Sortie : systemd 252 (252.22-1~deb12u1)

Architecture de systemd

PID 1 : le processus initial

systemd est le premier processus lancé par le noyau Linux (PID 1). Il est responsable du démarrage de tous les autres processus et services du système. Contrairement à SysVinit qui exécutait les scripts séquentiellement, systemd parallélise le démarrage grâce à son système de dépendances.

Les Units

L'unité de base de systemd est l'unit. Chaque ressource gérée par systemd est représentée par un fichier unit. Il existe plusieurs types :

  • .service : un daemon ou un processus (nginx, sshd, postgresql)
  • .socket : un socket réseau ou IPC pour l'activation à la demande
  • .timer : un minuteur qui déclenche un service (alternative à cron)
  • .target : un groupe d'units (équivalent des runlevels)
  • .mount / .automount : un point de montage du système de fichiers
  • .path : surveillance de modifications de fichiers
  • .slice : groupe de contrôle des ressources (cgroups)

Emplacements des fichiers unit

# Units installées par les paquets (ne pas modifier)
/usr/lib/systemd/system/

# Units personnalisées et overrides (prioritaires)
/etc/systemd/system/

# Units temporaires créées à l'exécution
/run/systemd/system/

# Lister tous les fichiers unit disponibles
systemctl list-unit-files

Dépendances et ordre de démarrage

systemd résout automatiquement les dépendances entre units. Les directives Requires=, Wants=, After= et Before= définissent les relations :

# Visualiser les dépendances d'un service
systemctl list-dependencies nginx.service

# Afficher l'arbre inversé (qui dépend de ce service)
systemctl list-dependencies --reverse nginx.service

Gestion des services

Commandes essentielles avec systemctl

systemctl est la commande centrale pour interagir avec systemd. Voici les opérations fondamentales :

# Démarrer un service
sudo systemctl start nginx

# Arrêter un service
sudo systemctl stop nginx

# Redémarrer un service (arrêt + démarrage)
sudo systemctl restart nginx

# Recharger la configuration sans redémarrer
sudo systemctl reload nginx

# Redémarrer si actif, ne rien faire sinon
sudo systemctl try-restart nginx

# Recharger ou redémarrer si reload non supporté
sudo systemctl reload-or-restart nginx

État et informations

# État détaillé d'un service
systemctl status nginx

# Vérifier si un service est actif
systemctl is-active nginx

# Vérifier si un service est activé au boot
systemctl is-enabled nginx

# Vérifier si un service a échoué
systemctl is-failed nginx

# Lister tous les services actifs
systemctl list-units --type=service --state=running

# Lister les services en échec
systemctl --failed

Activation au démarrage

# Activer un service au boot
sudo systemctl enable nginx

# Désactiver un service au boot
sudo systemctl disable nginx

# Activer ET démarrer en une commande
sudo systemctl enable --now nginx

# Désactiver ET arrêter en une commande
sudo systemctl disable --now nginx

# Empêcher un service d'être démarré (masquage)
sudo systemctl mask nginx

# Annuler le masquage
sudo systemctl unmask nginx
Attention : mask vs disable
disable retire le lien de démarrage automatique mais le service peut encore être lancé manuellement. mask rend le service complètement impossible à démarrer, même manuellement. Utilisez mask pour les services que vous voulez définitivement empêcher de fonctionner.

Création de services personnalisés

Structure d'un fichier unit

Un fichier unit .service se compose de trois sections principales :

[Unit]
Description=Mon Application Web Python
Documentation=https://example.com/docs
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/mon-app
Environment=ENV=production
EnvironmentFile=/opt/mon-app/.env
ExecStartPre=/opt/mon-app/venv/bin/python manage.py migrate
ExecStart=/opt/mon-app/venv/bin/gunicorn app:application --bind 0.0.0.0:8000
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mon-app

[Install]
WantedBy=multi-user.target

Détail des sections

  • [Unit] : métadonnées et dépendances. After= contrôle l'ordre de démarrage, Wants= déclare une dépendance souple
  • [Service] : comportement du service. ExecStart= est la commande principale, Restart= définit la politique de redémarrage
  • [Install] : cible d'activation. WantedBy=multi-user.target signifie que le service s'active en mode multi-utilisateur standard

Déployer un service personnalisé

# Créer le fichier unit
sudo nano /etc/systemd/system/mon-app.service

# Recharger la configuration systemd
sudo systemctl daemon-reload

# Activer et démarrer le service
sudo systemctl enable --now mon-app

# Vérifier le fonctionnement
systemctl status mon-app
Conseil : overrides sans modifier le fichier original
Pour modifier un service installé par un paquet sans toucher au fichier original, utilisez systemctl edit nginx.service. Cela crée un fichier override dans /etc/systemd/system/nginx.service.d/override.conf qui est prioritaire.

Types de services

La directive Type= dans la section [Service] définit comment systemd détermine que le service a démarré avec succès :

  • simple (défaut) : systemd considère le service démarré dès que ExecStart= est lancé. Idéal pour les processus qui restent en avant-plan.
  • forking : le processus se fork et le parent quitte. systemd attend que le parent se termine. Utilisez PIDFile= pour suivre le processus enfant.
  • oneshot : similaire à simple, mais systemd attend que le processus se termine avant de considérer le service actif. Idéal pour les scripts d'initialisation.
  • notify : le service envoie un signal à systemd via sd_notify() quand il est prêt. Le plus fiable pour les applications qui le supportent.
  • exec : similaire à simple, mais systemd attend que le binaire soit effectivement exécuté (après le exec()) avant de considérer le démarrage réussi.
# Exemple : service forking (daemon classique)
[Service]
Type=forking
PIDFile=/var/run/mon-daemon.pid
ExecStart=/usr/sbin/mon-daemon --daemon

# Exemple : service oneshot (script de configuration)
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/configure-network.sh
ExecStop=/usr/local/bin/deconfigure-network.sh

Timers systemd

Les timers systemd sont une alternative moderne et plus puissante à cron. Chaque timer est associé à un service du même nom qu'il déclenche.

Créer un timer

D'abord, créez le service qui sera déclenché :

# /etc/systemd/system/backup-db.service
[Unit]
Description=Sauvegarde quotidienne de la base de données

[Service]
Type=oneshot
User=postgres
ExecStart=/opt/scripts/backup-database.sh
StandardOutput=journal

Ensuite, créez le timer associé :

# /etc/systemd/system/backup-db.timer
[Unit]
Description=Planification de la sauvegarde quotidienne

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target

Syntaxe OnCalendar

# Format : DayOfWeek Year-Month-Day Hour:Minute:Second
OnCalendar=*-*-* 02:00:00          # Tous les jours à 2h
OnCalendar=Mon *-*-* 09:00:00      # Chaque lundi à 9h
OnCalendar=*-*-01 00:00:00         # Le 1er de chaque mois
OnCalendar=hourly                   # Toutes les heures
OnCalendar=weekly                   # Chaque semaine

# Autres déclencheurs basés sur le temps
OnBootSec=5min                      # 5 minutes après le boot
OnUnitActiveSec=1h                  # 1 heure après la dernière activation

# Valider la syntaxe d'un calendrier
systemd-analyze calendar "Mon *-*-* 09:00:00"

Gestion des timers

# Activer et démarrer le timer
sudo systemctl enable --now backup-db.timer

# Lister tous les timers actifs
systemctl list-timers --all

# Déclencher manuellement le service associé
sudo systemctl start backup-db.service
Avantage Persistent=true
Avec Persistent=true, si la machine était éteinte au moment prévu, le timer se déclenche immédiatement au prochain démarrage. Cron n'offre pas cette fonctionnalité nativement.

Journald : gestion centralisée des logs

journald est le système de journalisation intégré à systemd. Il collecte et indexe les logs de tous les services, du noyau et des messages syslog dans un format binaire structuré.

Consultation des logs avec journalctl

# Tous les logs du système
journalctl

# Logs d'un service spécifique
journalctl -u nginx.service

# Suivre les logs en temps réel
journalctl -u nginx.service -f

# Logs depuis le dernier boot
journalctl -b

# Logs du boot précédent
journalctl -b -1

# Filtrage par date
journalctl --since "2026-02-12 08:00:00" --until "2026-02-12 12:00:00"
journalctl --since "1 hour ago"

# Filtrage par priorité (0=emerg à 7=debug)
journalctl -p err                   # Erreurs et au-dessus
journalctl -p warning -u nginx      # Warnings d'nginx

# Logs du noyau uniquement
journalctl -k

# Format de sortie personnalisé
journalctl -u nginx -o json-pretty  # Format JSON
journalctl -u nginx -o short-iso    # Timestamps ISO

Persistance des logs

Par défaut sur certaines distributions, les logs ne survivent pas au redémarrage. Pour activer la persistance :

# Créer le répertoire de stockage persistant
sudo mkdir -p /var/log/journal

# Redémarrer journald pour appliquer
sudo systemctl restart systemd-journald

Configuration et rotation

Le fichier /etc/systemd/journald.conf contrôle le comportement de journald :

# /etc/systemd/journald.conf
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=500M
SystemMaxFileSize=50M
MaxRetentionSec=1month
ForwardToSyslog=no
# Voir l'espace disque utilisé par les logs
journalctl --disk-usage

# Nettoyer les anciens logs (garder 500M)
sudo journalctl --vacuum-size=500M

# Nettoyer les logs de plus de 2 semaines
sudo journalctl --vacuum-time=2weeks

Targets et processus de boot

Les targets sont des groupes d'units qui représentent un état du système. Elles remplacent les anciens runlevels de SysVinit :

  • poweroff.target (runlevel 0) : arrêt du système
  • rescue.target (runlevel 1) : mode mono-utilisateur de secours
  • multi-user.target (runlevel 3) : mode multi-utilisateur sans interface graphique
  • graphical.target (runlevel 5) : mode graphique complet
  • reboot.target (runlevel 6) : redémarrage
  • emergency.target : mode d'urgence minimal (shell root)
# Voir la target par défaut
systemctl get-default

# Changer la target par défaut
sudo systemctl set-default multi-user.target

# Basculer vers une target immédiatement
sudo systemctl isolate rescue.target

# Lister les units d'une target
systemctl list-dependencies multi-user.target

Socket activation

La socket activation permet à systemd d'écouter sur un port et de ne démarrer le service associé que lorsqu'une connexion arrive. Cela réduit la consommation de ressources et accélère le boot.

# /etc/systemd/system/mon-api.socket
[Unit]
Description=Socket pour Mon API

[Socket]
ListenStream=8080
Accept=no
BindIPv6Only=both

[Install]
WantedBy=sockets.target
# /etc/systemd/system/mon-api.service
[Unit]
Description=Mon API REST
Requires=mon-api.socket

[Service]
Type=simple
User=apiuser
ExecStart=/opt/api/bin/server
StandardOutput=journal

[Install]
WantedBy=multi-user.target
# Activer le socket (pas le service directement)
sudo systemctl enable --now mon-api.socket

# Le service démarre automatiquement à la première connexion
curl http://localhost:8080/health

Contrôle des ressources

systemd s'intègre avec les cgroups v2 du noyau Linux pour limiter les ressources consommées par chaque service :

# Dans la section [Service] d'un fichier unit
[Service]
# Limiter le CPU à 50%
CPUQuota=50%

# Limiter la mémoire à 512 Mo (hard limit)
MemoryMax=512M

# Limite souple de mémoire (déclenche le swap)
MemoryHigh=400M

# Limiter les I/O disque
IOWeight=50
IOReadBandwidthMax=/dev/sda 10M
IOWriteBandwidthMax=/dev/sda 5M

# Limiter le nombre de processus
TasksMax=64
# Voir les ressources consommées par un service
systemctl status nginx.service     # Aperçu rapide
systemd-cgtop                      # Vue temps réel type top

# Appliquer des limites à chaud (temporaire)
sudo systemctl set-property nginx.service CPUQuota=30%
sudo systemctl set-property nginx.service MemoryMax=256M

# Voir les propriétés de ressources d'un service
systemctl show nginx.service -p CPUQuota,MemoryMax,TasksMax
Vérifier le support cgroups v2
Certaines fonctionnalités de contrôle de ressources nécessitent cgroups v2. Vérifiez avec mount | grep cgroup2 ou cat /sys/fs/cgroup/cgroup.controllers. Sur les systèmes récents (Debian 11+, Ubuntu 21.10+), cgroups v2 est activé par défaut.

Analyse et debugging

systemd-analyze fournit des outils puissants pour comprendre et optimiser le processus de démarrage :

# Temps total de démarrage
systemd-analyze time

# Temps de démarrage par service (trié par durée)
systemd-analyze blame

# Chaîne critique : le chemin le plus long du boot
systemd-analyze critical-chain

# Chaîne critique d'un service spécifique
systemd-analyze critical-chain nginx.service

# Générer un graphique SVG du boot
systemd-analyze plot > boot-chart.svg

# Vérifier la syntaxe d'un fichier unit
systemd-analyze verify /etc/systemd/system/mon-app.service

# Analyser le score de sécurité d'un service
systemd-analyze security nginx.service

# Analyser la sécurité de tous les services
systemd-analyze security
Optimisation du boot
Utilisez systemd-analyze blame pour identifier les services les plus lents au démarrage, puis critical-chain pour comprendre quelles dépendances bloquent. Vous pourrez ensuite désactiver les services inutiles ou optimiser leurs dépendances.

Sécurisation des services

systemd offre de nombreuses directives de sandboxing pour isoler les services et réduire la surface d'attaque. Voici les options les plus importantes :

[Service]
# Protection du système de fichiers
ProtectSystem=strict           # / en lecture seule sauf /dev, /proc, /sys
ReadWritePaths=/var/lib/mon-app /var/log/mon-app
ProtectHome=true               # /home, /root, /run/user inaccessibles
PrivateTmp=true                # /tmp isolé pour ce service

# Isolation réseau et périphériques
PrivateDevices=true            # Pas d'accès aux périphériques physiques
ProtectKernelTunables=true     # /proc/sys en lecture seule
ProtectKernelModules=true      # Impossible de charger des modules
ProtectControlGroups=true      # /sys/fs/cgroup en lecture seule

# Restriction des privilèges
NoNewPrivileges=true           # Empêche l'escalade de privilèges
CapabilityBoundingSet=CAP_NET_BIND_SERVICE  # Seules capabilities autorisées
AmbientCapabilities=CAP_NET_BIND_SERVICE

# Filtrage des appels système
SystemCallFilter=@system-service  # N'autorise que les syscalls standards
SystemCallArchitectures=native    # Bloque les syscalls d'autres architectures

# Restrictions supplémentaires
RestrictNamespaces=true        # Pas de création de namespaces
RestrictRealtime=true          # Pas de scheduling temps réel
RestrictSUIDSGID=true          # Pas de fichiers SUID/SGID
LockPersonality=true           # Verrouille le domaine d'exécution
MemoryDenyWriteExecute=true    # Empêche W^X (code auto-modifiant)
# Évaluer le niveau de sécurité actuel d'un service
systemd-analyze security nginx.service

# Sortie : EXPOSURE LEVEL avec un score de 0 (sûr) à 10 (non sécurisé)
# L'objectif est d'obtenir un score inférieur à 5
Approche progressive
Activez les directives de sécurité une par une et testez votre service après chaque ajout. Commencez par ProtectSystem=strict, PrivateTmp=true et NoNewPrivileges=true qui sont compatibles avec la plupart des services, puis ajoutez progressivement les autres restrictions.

Troubleshooting

Diagnostic d'un service en échec

# 1. Vérifier l'état et les dernières lignes de log
systemctl status mon-app.service

# 2. Consulter les logs complets avec contexte
journalctl -xeu mon-app.service

# 3. Vérifier la syntaxe du fichier unit
systemd-analyze verify /etc/systemd/system/mon-app.service

# 4. Tester la commande manuellement
sudo -u appuser /opt/mon-app/venv/bin/gunicorn app:application

# 5. Vérifier les permissions
ls -la /opt/mon-app/
namei -l /opt/mon-app/venv/bin/gunicorn

Problèmes courants et solutions

  • Service en boucle de redémarrage : Vérifiez StartLimitBurst et StartLimitIntervalSec dans la section [Unit]. Utilisez systemctl reset-failed pour réinitialiser le compteur.
  • "daemon-reload" oublié : Après toute modification d'un fichier unit, exécutez sudo systemctl daemon-reload pour que systemd prenne en compte les changements.
  • Permissions insuffisantes : Vérifiez que l'utilisateur défini par User= a les droits nécessaires sur les fichiers et répertoires.
  • Dépendance manquante : Si un service ne démarre pas à cause d'un autre, vérifiez les directives After= et Requires=.
  • Conflit avec un override : Vérifiez les overrides avec systemctl cat mon-app.service qui affiche la configuration effective complète.
# Réinitialiser un service en échec
sudo systemctl reset-failed mon-app.service

# Voir la configuration effective (fichier + overrides)
systemctl cat mon-app.service

# Recharger après modification
sudo systemctl daemon-reload
sudo systemctl restart mon-app.service

Conclusion

systemd est bien plus qu'un simple gestionnaire de services : c'est un écosystème complet d'administration système. En maîtrisant ses composants, vous disposez des outils pour :

  • Gérer efficacement le cycle de vie de tous vos services avec systemctl
  • Créer des services personnalisés robustes avec redémarrage automatique et gestion des dépendances
  • Planifier des tâches récurrentes avec les timers, plus fiables que cron
  • Centraliser et analyser vos logs avec journald et journalctl
  • Sécuriser vos services avec le sandboxing intégré et réduire la surface d'attaque
  • Diagnostiquer et optimiser le démarrage du système avec systemd-analyze
  • Contrôler finement les ressources CPU, mémoire et I/O de chaque service

La maîtrise de systemd est une compétence fondamentale pour tout administrateur système Linux. Prenez le temps d'explorer chaque fonctionnalité progressivement et de consulter les pages de manuel (man systemd.service, man systemd.exec, man journalctl) pour approfondir chaque sujet.

Morgann Riu

Écrit par

Morgann Riu

Expert en cybersécurité et administration Linux. Je partage mes connaissances à travers des tutoriels gratuits et des formations pour aider les administrateurs systèmes et développeurs à sécuriser leurs infrastructures.

Partager ce tutoriel

Cet article vous a plu ?

Commentaires

Checklist Sécurité Linux

30 points essentiels pour sécuriser un serveur Linux. Recevez aussi les nouveaux tutoriels par email.

Pas de spam. Désabonnement en 1 clic.