
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é.