What Is the ansible service Module?
The ansible service module (ansible.builtin.service) manages system services — start, stop, restart, reload, and enable services for boot. It works across init systems (systemd, SysV, Upstart). For systemd-specific features, use ansible.builtin.systemd.
Use this module when you want a portable service task that works across Linux init systems; switch to ansible.builtin.systemd only when you need systemd-only options such as daemon_reload, masked, or scope.
Basic Usage
# Start a service
- name: Start nginx
ansible.builtin.service:
name: nginx
state: started
# Stop a service
- name: Stop nginx
ansible.builtin.service:
name: nginx
state: stopped
# Restart a service
- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
# Reload configuration (no downtime)
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
Start and Enable at Boot
# Start now AND enable at boot
- name: Ensure nginx is running and enabled
ansible.builtin.service:
name: nginx
state: started
enabled: true
# Enable at boot without starting now
- name: Enable service at boot
ansible.builtin.service:
name: nginx
enabled: true
# Disable from boot
- name: Disable service at boot
ansible.builtin.service:
name: nginx
enabled: false
Parameters
| Parameter | Description |
|---|---|
name | Service name (required) |
state | started, stopped, restarted, reloaded |
enabled | Start at boot: true/false |
pattern | Process name pattern (for SysV init detection) |
sleep | Seconds to sleep between stop and start (for restarted) |
service vs systemd
# service — works on any init system
- ansible.builtin.service:
name: nginx
state: started
# systemd — systemd-specific features
- ansible.builtin.systemd:
name: nginx
state: started
daemon_reload: true # Reload systemd after unit file change
scope: system # system, user, or global
no_block: true # Don't wait for completion
masked: false # Unmask a service
Use service for portability. Use systemd when you need daemon_reload, masked, or scope.
Common Patterns
Deploy Config and Restart
---
- name: Deploy web server
hosts: webservers
become: true
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Deploy config
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: "nginx -t -c %s"
notify: Reload nginx # Only restart when config changes
- name: Ensure nginx is running
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
Manage Multiple Services
- name: Ensure all services are running
ansible.builtin.service:
name: "{{ item }}"
state: started
enabled: true
loop:
- nginx
- redis-server
- postgresql
- name: Stop unnecessary services
ansible.builtin.service:
name: "{{ item }}"
state: stopped
enabled: false
loop:
- apache2
- sendmail
- cups
ignore_errors: true # Don't fail if service doesn't exist
Check Service Status Before Acting
- name: Check if nginx is running
ansible.builtin.command: systemctl is-active nginx
register: nginx_status
ignore_errors: true
changed_when: false
- name: Start nginx if not running
ansible.builtin.service:
name: nginx
state: started
when: nginx_status.rc != 0
- name: Show status
ansible.builtin.debug:
msg: "nginx is {{ 'running' if nginx_status.rc == 0 else 'stopped' }}"
Deploy Custom systemd Service
- name: Deploy systemd service file
ansible.builtin.template:
src: myapp.service.j2
dest: /etc/systemd/system/myapp.service
mode: "0644"
notify:
- Reload systemd
- Restart myapp
- name: Enable and start service
ansible.builtin.systemd:
name: myapp
state: started
enabled: true
daemon_reload: true
handlers:
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
- name: Restart myapp
ansible.builtin.systemd:
name: myapp
state: restarted
templates/myapp.service.j2:
[Unit]
Description={{ app_name }}
After=network.target
[Service]
Type=simple
User={{ app_user }}
WorkingDirectory={{ app_dir }}
ExecStart={{ app_dir }}/bin/start --port {{ app_port }}
Restart=always
RestartSec=5
Environment=APP_ENV={{ app_env }}
[Install]
WantedBy=multi-user.target
Rolling Restart
# Restart services one host at a time
- name: Rolling restart
hosts: webservers
serial: 1 # One host at a time
become: true
tasks:
- name: Restart application
ansible.builtin.service:
name: myapp
state: restarted
- name: Wait for service to be healthy
ansible.builtin.uri:
url: "http://localhost:8080/health"
status_code: 200
retries: 10
delay: 3
register: health
until: health.status == 200
Mask/Unmask Services (systemd)
# Mask a service (prevent it from starting)
- name: Mask apache2
ansible.builtin.systemd:
name: apache2
masked: true
# Unmask
- name: Unmask apache2
ansible.builtin.systemd:
name: apache2
masked: false
state Behavior
| State | Action |
|---|---|
started | Start if stopped; no action if already running |
stopped | Stop if running; no action if already stopped |
restarted | Always stops and starts (even if running) |
reloaded | Reload config without full restart |
started and stopped are idempotent. restarted always causes a change — use handlers to restart only when needed.
Troubleshooting
"Could not find the requested service"
Service name might differ:
# Find the actual service name
systemctl list-units --type=service | grep nginx
# Output: nginx.service
# Some services have different names
# RedHat: httpd vs Debian: apache2
# RedHat: mariadb vs Debian: mysql
"Unable to restart service: daemon-reload required"
After changing a unit file, reload systemd:
- ansible.builtin.systemd:
daemon_reload: true
- ansible.builtin.service:
name: myapp
state: restarted
Service Starts but Immediately Stops
Check the service logs:
- name: Check service logs
ansible.builtin.command: journalctl -u myapp --no-pager -n 20
register: logs
- debug:
var: logs.stdout_lines
Related Articles
Conclusion
ansible.builtin.service handles service lifecycle: start, stop, restart, reload, and boot enablement. Use state: started + enabled: true for services that should always be running. Use handlers with notify to restart only when configuration changes. For systemd-specific features (daemon_reload, masking, scoping), use ansible.builtin.systemd. Prefer reloaded over restarted when possible — it applies config changes without downtime.