
Sur RHEL 7+, Ubuntu 16.04+ et toute distribution moderne, ansible.builtin.systemd_service est le module recommandé pour gérer les services. Il remplace l'ancien service: (encore présent mais legacy) avec des options spécifiques à systemd : daemon_reload:, masked:, et la distinction claire entre state: (état actuel) et enabled: (au boot).
Cas d'usage typiques RHCE 2026 : démarrer sshd, chronyd, firewalld ; déposer un unit file custom pour un service applicatif ; masquer un service dangereux (rpcbind, cups).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- La distinction
state:vsenabled:, pourquoi les deux options sont nécessaires. - L'option
daemon_reload: trueaprès modification d'un unit file.service. - Le mécanisme
masked: true, empêcher tout démarrage du service. - La différence
reloadedvsrestarted, recharger sans coupure.
Prérequis
Section intitulée « Prérequis »- Connaître les bases de systemd (
systemctl start,enable,status). - Avoir lu Module package, l'installation précède toujours le start.
state vs enabled, deux options indépendantes
Section intitulée « state vs enabled, deux options indépendantes »- name: Demarrer sshd MAINTENANT ansible.builtin.systemd_service: name: sshd state: startedstate: gère l'état immédiat : started (démarrer si arrêté), stopped, restarted (redémarrer toujours), reloaded (rechargement à chaud).
- name: Activer sshd au BOOT ansible.builtin.systemd_service: name: sshd enabled: trueenabled: gère le démarrage au boot : true (équivalent systemctl enable), false (équivalent systemctl disable).
Les deux sont indépendants : un service peut être démarré sans être enabled (start manuel après un reboot), ou enabled mais arrêté (planifié pour le prochain reboot). En production, les deux ensemble est l'usage standard :
- name: Demarrer ET activer sshd ansible.builtin.systemd_service: name: sshd state: started enabled: truerestarted vs reloaded
Section intitulée « restarted vs reloaded »state: | Effet | Coupure ? |
|---|---|---|
restarted | Stop + Start (redémarre le processus) | Oui, brève (ms à quelques secondes selon le service) |
reloaded | Envoie SIGHUP (rechargement de config) | Non, pas d'arrêt, juste reload |
Préférer reloaded quand le service le supporte (nginx, httpd, sshd, firewalld), pas de coupure pour les clients connectés. restarted reste nécessaire pour un changement d'unit file ou un changement majeur que SIGHUP ne couvre pas.
daemon_reload, recharger systemd lui-même
Section intitulée « daemon_reload, recharger systemd lui-même »Quand on dépose un nouveau unit file dans /etc/systemd/system/, systemd ne le voit pas tant qu'on n'a pas fait systemctl daemon-reload. Sans ça, start échouerait avec "unit not found".
- name: Deposer unit file myapp ansible.builtin.copy: src: files/myapp.service dest: /etc/systemd/system/myapp.service mode: "0644"
- name: Recharger systemd et demarrer myapp ansible.builtin.systemd_service: name: myapp state: started enabled: true daemon_reload: truedaemon_reload: true déclenche systemctl daemon-reload avant d'agir sur myapp, l'unit file est pris en compte, puis le service démarre.
Pas besoin de daemon_reload si vous modifiez juste l'état d'un service existant (state: started sur sshd). Réservé aux nouveaux unit files ou aux modifs d'un unit file existant.
masked, interdire le start
Section intitulée « masked, interdire le start »- name: Masquer rpcbind (interdit toute tentative de start) ansible.builtin.systemd_service: name: rpcbind state: stopped enabled: false masked: truemasked: true lie l'unit file à /dev/null, toute commande systemctl start rpcbind échoue silencieusement, même par un humain. Pattern de durcissement pour des services qu'on interdit absolument.
Différence avec enabled: false : disabled empêche le démarrage au boot, mais systemctl start <service> manuel marche encore. masked interdit toute forme de démarrage.
Démarrer plusieurs services, boucle
Section intitulée « Démarrer plusieurs services, boucle »- name: Demarrer la stack monitoring ansible.builtin.systemd_service: name: "{{ item }}" state: started enabled: true loop: - prometheus - grafana-server - node_exporterChaque itération est une opération systemd indépendante. Pour 50 services, c'est lent, mais c'est rare d'avoir 50 services à démarrer en parallèle.
Notification depuis un handler
Section intitulée « Notification depuis un handler »Pattern classique : modifier sshd_config → recharger sshd via un handler.
- name: Modifier sshd_config ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PermitRootLogin' line: 'PermitRootLogin no' notify: Reload sshd
handlers: - name: Reload sshd ansible.builtin.systemd_service: name: sshd state: reloadedLe handler ne tourne qu'à la fin du play (et seulement si la tâche a notifié). Voir Handlers pour le détail.
Pièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Fix |
|---|---|---|
"Unit not found" après copy: d'un unit file | Pas de daemon_reload | Ajouter daemon_reload: true |
| Service démarre au play mais pas au reboot | enabled: false (ou pas spécifié) | Ajouter enabled: true |
state: reloaded échoue | Service ne supporte pas SIGHUP | Utiliser state: restarted |
systemctl start <service> marche en CLI mais pas après mask | Service est masked | masked: false puis state: started |
enabled: true mais service ne démarre pas au boot | Unit file n'a pas de [Install] section | Ajouter [Install]\nWantedBy=multi-user.target à l'unit file |
À retenir
Section intitulée « À retenir »state:= état immédiat (start/stop/restart/reload).enabled:= démarrage au boot. Indépendants.daemon_reload: trueest obligatoire après un nouveau unit file ou une modif d'un unit existant.reloaded>restartedquand le service le supporte, pas de coupure.masked: trueest l'arme nucléaire, interdit tout start, même manuel.- Section
[Install]dans l'unit file est obligatoire pour queenabled: truefonctionne.
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »Cette page a un lab d'accompagnement : labs/modules-services/systemd/ dans stephrobert/ansible-training.
Challenge, sur web1.lab :
- Installer
chrony(NTP). - Démarrer + activer
chronyd. - Déposer un unit file custom
lab-marker.service(oneshot RemainAfterExit). daemon_reload+ start + enablelab-marker.
Validation pytest+testinfra :
ansible-playbook solution.ymlpytest -v labs/modules-services/systemd/challenge/tests/5 tests vérifient chrony installé, chronyd actif et activé, l'unit file présent, lab-marker activé et /var/run/lab-marker.flag touché.