ansible.builtin.service: Manage Services with Ansible (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
How to restart, start, stop, and enable services with Ansible service module. Manage systemd, SysV, and Windows services with handlers and examples.

How to restart services on remote hosts with Ansible?
I'm going to show you a live Playbook with some simple Ansible code. I'm Luca Berton and welcome to today's episode of Ansible Pilot.See also: Add Secondary Groups to Linux Users with Ansible Playbook
Ansible restart services on remote hosts
Today we're talking about the Ansible moduleservice.
The full name is ansible.builtin.service which means is part of the collection of modules "builtin" with ansible and shipped with it.
This module is pretty stable and out for years.
The purpose is to controls services on remote hosts.
The Supported service systems include BSD, OpenRC, SysV, Solaris SMF, systemd, and upstart.
For Windows targets, use the ansible.windows.win_service module instead.
Parameters
• name _path_ - name of the service • state _string_ - started / stopped / restarted / reloaded • enabled _boolean_ - no/yes • sleep _integer_ - seconds after the restart • arguments/args _string_ - extra argsThe parameter list is pretty wide but I'll summarize the most useful. The only required parameter is "name" that specifies the name of the service. At least one between the "state" and "enabled" parameters is mandatory. The "state" parameter defines the action that we are going to take. It has four alternatives options: "started" and "stopped" options allow you to run or stop the service. "restarted" is a combination of stop and start - you could also customize the number of seconds between using the "sleep" parameter The "reloaded" option is useful if the service needs to reload the configuration file. The "enable" parameter allows you to decide if the service should start on boot or not. The "arguments or args" parameter allows you to specify some additional arguments provided on the command line.
## Playbook Let's jump into a real-life playbook on how to controls services on remote hosts with Ansible Playbook. • service.yml
---
- name: service module Playbook
hosts: all
become: true
tasks:
- name: sshd restart
ansible.builtin.service:
name: sshd
state: restarted
enabled: true
See also: Ansible Linux Users and Groups: Complete Management Guide (Examples)
Conclusion
Now you know how to restart and control services on remote hosts with Ansible.Service Management Examples
Start and enable
- name: Start and enable nginx
ansible.builtin.service:
name: nginx
state: started
enabled: true
become: true
Stop a service
- name: Stop old application
ansible.builtin.service:
name: myapp-legacy
state: stopped
enabled: false
become: true
Reload (without restart)
- name: Reload nginx config
ansible.builtin.service:
name: nginx
state: reloaded
become: true
See also: Ansible code in RHSB-2021-009 Log4Shell - Remote Code Execution - log4j (CVE-2021-44228)
Using as a Handler
tasks:
- name: Update nginx config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
become: true
handlers:
- name: restart nginx
ansible.builtin.service:
name: nginx
state: restarted
become: true
service vs systemd Module
| Module | Scope | Best For |
|--------|-------|----------|
| service | Generic (systemd, SysV, OpenRC) | Cross-platform |
| systemd | systemd only | systemd-specific features |
systemd-specific features
- name: Restart with systemd (daemon-reload)
ansible.builtin.systemd:
name: myapp
state: restarted
daemon_reload: true # Reload unit files first
become: true
- name: Mask a service (prevent starting)
ansible.builtin.systemd:
name: bluetooth
masked: true
become: true
Check Service Status
- name: Gather service facts
ansible.builtin.service_facts:
- name: Check if nginx is running
ansible.builtin.debug:
msg: "nginx is {{ ansible_facts.services['nginx.service'].state }}"
- name: Fail if critical service is down
ansible.builtin.fail:
msg: "PostgreSQL is not running!"
when: ansible_facts.services['postgresql.service'].state != 'running'
Manage Multiple Services
- name: Ensure core services are running
ansible.builtin.service:
name: "{{ item }}"
state: started
enabled: true
loop:
- nginx
- postgresql
- redis
become: true
Windows Services
- name: Start Windows service
ansible.windows.win_service:
name: W3SVC # IIS
state: started
start_mode: auto
FAQ
What's the difference between restarted and reloaded?
•restarted: Stops and starts the service (brief downtime)
• reloaded: Sends SIGHUP to reload config without stopping (zero downtime, but not all services support it)
How do I handle services that don't exist?
- name: Check if service exists
ansible.builtin.command: systemctl list-unit-files {{ service_name }}.service
register: svc_check
changed_when: false
failed_when: false
- name: Restart if exists
ansible.builtin.service:
name: "{{ service_name }}"
state: restarted
when: svc_check.rc == 0
Why does 'started' not restart the service?
state: started only starts if stopped. Use state: restarted to always restart.
Restart Service
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
become: true
Start and Enable
- service:
name: nginx
state: started
enabled: true
become: true
Stop Service
- service:
name: nginx
state: stopped
become: true
Reload (No Downtime)
- service:
name: nginx
state: reloaded
become: true
Use with Handlers (Best Practice)
# tasks/main.yml
- name: Deploy config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
become: true
- name: Deploy site config
template:
src: site.conf.j2
dest: /etc/nginx/conf.d/site.conf
notify: reload nginx
become: true
# handlers/main.yml
- name: restart nginx
service: { name: nginx, state: restarted }
become: true
- name: reload nginx
service: { name: nginx, state: reloaded }
become: true
systemd Module (Advanced)
- ansible.builtin.systemd:
name: myapp
state: restarted
daemon_reload: true # Reload unit files first
become: true
# Enable and start
- systemd:
name: myapp
state: started
enabled: true
masked: false
become: true
Manage Multiple Services
- service:
name: "{{ item }}"
state: started
enabled: true
loop:
- nginx
- redis
- postgresql
become: true
Check Service Status
- command: systemctl is-active nginx
register: nginx_status
changed_when: false
failed_when: false
- debug:
msg: "nginx is {{ 'running' if nginx_status.rc == 0 else 'stopped' }}"
Wait After Restart
- service: { name: myapp, state: restarted }
become: true
- wait_for:
port: 8080
delay: 5
timeout: 60
Windows Services
- ansible.windows.win_service:
name: W3SVC # IIS
state: restarted
- win_service:
name: MyApp
state: started
start_mode: auto
service vs systemd
| Feature | service | systemd | |---------|---------|---------| | Init systems | All (systemd, SysV, etc.) | systemd only | | daemon_reload | No | Yes | | Scope | No | Yes (user/system) | | Masking | No | Yes | | Portability | More portable | systemd only |
FAQ
restart vs reload?
restart stops and starts the service (brief downtime). reload re-reads config without stopping (no downtime, but not all services support it).
Why use handlers instead of direct restart?
Handlers run once at the end, even if notified multiple times. Direct restarts run immediately and can restart unnecessarily.
Service not found?
Check the exact service name: systemctl list-units --type=service | grep myapp
Related Articles
• Ansible privilege escalation patterns • Ansible roles guide • configuring Windows services via AnsibleCategory: troubleshooting
Watch the video: ansible.builtin.service: Manage Services with Ansible (Complete Guide) — Video Tutorial