AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible service Module: Start, Stop & Restart Services (ansible.builtin.service)

By Luca Berton · Published 2024-01-01 · Category: installation

How to manage services with Ansible service module (ansible.builtin.service). Start, stop, restart, enable, disable systemd and init services.

The ansible.builtin.service module manages services across any init system — systemd, SysVinit, OpenRC, Upstart. It abstracts the differences so the same playbook works on any Linux distribution.

Basic Operations

# 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

See also: Ansible service Module: Start, Stop, Restart Services (Complete Guide)

Enable on Boot

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

# Enable without starting - ansible.builtin.service: name: nginx enabled: true

# Disable and stop - ansible.builtin.service: name: nginx state: stopped enabled: false

service vs systemd Module

# ansible.builtin.service — works on any init system
- ansible.builtin.service:
    name: nginx
    state: started

# ansible.builtin.systemd — systemd-specific features - ansible.builtin.systemd: name: nginx state: started daemon_reload: true # Only available in systemd module scope: system # system, user, or global masked: false # Unmask a service

| Feature | service | systemd | |---------|---------|---------| | Start/stop/restart | ✅ | ✅ | | Enable/disable | ✅ | ✅ | | daemon-reload | ❌ | ✅ | | Mask/unmask | ❌ | ✅ | | User services | ❌ | ✅ | | Cross-platform | ✅ | ❌ (systemd only) |

Rule of thumb: Use service for portability. Use systemd when you need daemon_reload or masking.

See also: ansible.builtin.service: Manage Services with Ansible (Complete Guide)

Common Patterns

Install and Start

- name: Install and enable Nginx
  ansible.builtin.apt:
    name: nginx
    state: present

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

Handler Pattern (Restart on Config Change)

tasks:
  - name: Deploy nginx config
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: restart nginx

- name: Deploy site config ansible.builtin.template: src: site.conf.j2 dest: /etc/nginx/conf.d/mysite.conf notify: reload nginx

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

- name: reload nginx ansible.builtin.service: name: nginx state: reloaded

Validate Config Before Restart

- name: Deploy nginx config
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    validate: nginx -t -c %s
  notify: restart nginx

Conditional Service Name

- name: Restart web server
  ansible.builtin.service:
    name: "{{ (ansible_facts['os_family'] == 'Debian') | ternary('apache2', 'httpd') }}"
    state: restarted

Wait for Service Readiness

- name: Start application
  ansible.builtin.service:
    name: myapp
    state: started

- name: Wait for port to be ready ansible.builtin.wait_for: port: 8080 timeout: 30 delay: 5

- name: Verify health endpoint ansible.builtin.uri: url: http://localhost:8080/health status_code: 200 retries: 5 delay: 5

Multiple Services

- name: Start all required services
  ansible.builtin.service:
    name: "{{ item }}"
    state: started
    enabled: true
  loop:
    - nginx
    - postgresql
    - redis
    - myapp

Stop and Disable Unwanted Services

- name: Disable unnecessary services (CIS hardening)
  ansible.builtin.service:
    name: "{{ item }}"
    state: stopped
    enabled: false
  loop:
    - cups
    - avahi-daemon
    - rpcbind
    - bluetooth
  ignore_errors: true    # Some may not be installed

systemd-Specific Features

Daemon Reload

# After creating/modifying a .service unit file
- name: Deploy custom service unit
  ansible.builtin.template:
    src: myapp.service.j2
    dest: /etc/systemd/system/myapp.service
  notify: restart myapp

- name: Reload systemd daemon ansible.builtin.systemd: daemon_reload: true

- name: Start custom service ansible.builtin.systemd: name: myapp state: started enabled: true

Mask a Service

# Prevent a service from being started (even manually)
- name: Mask unnecessary service
  ansible.builtin.systemd:
    name: cups
    masked: true
    state: stopped

Create a systemd Service File

- name: Create service unit
  ansible.builtin.copy:
    dest: /etc/systemd/system/myapp.service
    content: |
      [Unit]
      Description=My Application
      After=network.target postgresql.service
      Requires=postgresql.service

[Service] Type=simple User=myapp WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/bin/start ExecReload=/bin/kill -HUP $MAINPID Restart=always RestartSec=5 Environment=NODE_ENV=production

[Install] WantedBy=multi-user.target mode: '0644' notify: - reload systemd - restart myapp

handlers: - name: reload systemd ansible.builtin.systemd: daemon_reload: true

- name: restart myapp ansible.builtin.systemd: name: myapp state: restarted

See also: Ansible Start & Enable Service on Boot: systemd Module Guide

Service State Checking

- name: Check if service is running
  ansible.builtin.service_facts:

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

- name: Fail if critical service not running ansible.builtin.fail: msg: "PostgreSQL is not running!" when: > 'postgresql.service' not in ansible_facts.services or ansible_facts.services['postgresql.service'].state != 'running'

FAQ

What's the difference between restarted and reloaded?

restarted stops and starts the service (brief downtime). reloaded sends a signal (usually SIGHUP) to re-read configuration without stopping — zero downtime. Not all services support reload; use restart as fallback.

Should I use service or systemd module?

Use ansible.builtin.service for cross-platform playbooks. Use ansible.builtin.systemd only when you need systemd-specific features like daemon_reload, masked, or user scope services. Most playbooks should use service.

How do I restart a service only when a config file changes?

Use the handler pattern: add notify: restart myservice to your template/copy task, and define a handler that restarts the service. Handlers only run when notified by a changed task.

Why does my service start but immediately stop?

Check the service logs with journalctl -u myservice -n 50. Common causes: wrong ExecStart path, missing dependencies, permission errors, port already in use. Test manually with systemctl start myservice && systemctl status myservice.

Conclusion

Use ansible.builtin.service for starting, stopping, and enabling services across any Linux distribution. Pair it with handlers for config-driven restarts, wait_for for readiness checks, and service_facts for state verification. Switch to the systemd module only when you need daemon-reload or masking.

Related Articles

flush_handlers in AnsibleAnsible template Module GuideAnsible ignore_errors GuideAnsible for Linux System Administration

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home