Introduction

The ansible.builtin.service module manages system services across all init systems — systemd, SysV init, OpenRC, and BSD rc.d. It's the universal way to start, stop, restart, and enable services on boot without worrying about the underlying init system.

Quick Reference

# Start a service
- ansible.builtin.service:
    name: nginx
    state: started

# Stop a service
- ansible.builtin.service:
    name: nginx
    state: stopped

# Restart a service
- ansible.builtin.service:
    name: nginx
    state: restarted

# Reload configuration (no downtime)
- ansible.builtin.service:
    name: nginx
    state: reloaded

# Enable on boot
- ansible.builtin.service:
    name: nginx
    enabled: true

# Start AND enable
- ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

Parameters

ParameterValuesDescription
namestringService name (required)
statestarted, stopped, restarted, reloadedDesired service state
enabledtrue/falseStart on boot
patternregexProcess name pattern for status check
sleepsecondsWait between stop and start (for restarted)
argumentsstringAdditional arguments for the service command

Common Patterns

Install and Start

- name: Install and start nginx
  hosts: webservers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Start and enable nginx
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

Restart on Configuration Change

- name: Configure and restart service
  hosts: webservers
  become: true
  tasks:
    - name: Deploy nginx config
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Restart nginx

  handlers:
    - name: Restart nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

Reload vs Restart

# Reload: re-read config without dropping connections
- name: Reload nginx (graceful)
  ansible.builtin.service:
    name: nginx
    state: reloaded

# Restart: full stop + start (brief downtime)
- name: Restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

Multiple Services

- name: Ensure core services running
  ansible.builtin.service:
    name: "{{ item }}"
    state: started
    enabled: true
  loop:
    - sshd
    - chronyd
    - rsyslog
    - firewalld

Stop and Disable

- name: Disable unnecessary services
  ansible.builtin.service:
    name: "{{ item }}"
    state: stopped
    enabled: false
  loop:
    - cups
    - bluetooth
    - avahi-daemon
  ignore_errors: true  # Some may not exist

service vs systemd Module

# ansible.builtin.service — universal, works everywhere
- ansible.builtin.service:
    name: nginx
    state: started

# ansible.builtin.systemd_service — systemd-specific features
- ansible.builtin.systemd_service:
    name: nginx
    state: started
    daemon_reload: true  # Only systemd supports this
    scope: system        # system or user
Featureservicesystemd
Cross-platform✅ All init systems❌ systemd only
daemon_reload❌✅
scope (user units)❌✅
Masked units❌✅
Timer units❌✅

Rule: Use service unless you need systemd-specific features.

Conditional Service Management

- name: Start service only if installed
  ansible.builtin.service:
    name: nginx
    state: started
  when: "'nginx' in ansible_facts.packages"

- name: Restart only if running
  ansible.builtin.service:
    name: myapp
    state: restarted
  when: ansible_facts.services['myapp.service'].state == 'running'

Check Service Status

- name: Gather service facts
  ansible.builtin.service_facts:

- name: Show nginx status
  ansible.builtin.debug:
    msg: "nginx is {{ ansible_facts.services['nginx.service'].state }}"

- name: Fail if critical service not running
  ansible.builtin.assert:
    that:
      - ansible_facts.services['sshd.service'].state == 'running'
    fail_msg: "SSHD is not running!"

Wait for Service to Be Ready

- name: Start database
  ansible.builtin.service:
    name: postgresql
    state: started

- name: Wait for PostgreSQL to accept connections
  ansible.builtin.wait_for:
    port: 5432
    host: localhost
    delay: 2
    timeout: 30

Troubleshooting

ErrorCauseFix
Could not find the requested serviceService not installedInstall package first
Unable to start serviceConfig error or port conflictCheck journalctl -u servicename
Service is maskedService deliberately disabledUse systemd module with masked: false
Idempotency: always "changed"Service doesn't report status correctlyUse pattern parameter
Service starts but crashesDependencies not metCheck logs, ensure deps are started first

Best Practices

  1. Use handlers for restarts — only restart when config actually changes
  2. Always set enabled: true alongside state: started — survives reboot
  3. Use reloaded over restarted when possible — avoids downtime
  4. Gather service_facts before conditionals — check state before acting
  5. Use wait_for after starting — verify the service is actually ready
  6. Use service module, not shell — idempotent and cross-platform

Conclusion

The ansible.builtin.service module manages services across all init systems. Use state: started with enabled: true for services that should always run. Use handlers to restart only on configuration changes. Check service readiness with wait_for after starting. Prefer service over systemd unless you need daemon_reload or user-scope units.