Ansible Fundamentals · Module 08 of 12

Modules & handlers

Use focused modules for state management and handlers for actions that should happen only after a real change.

Learning objectives

By the end of this module, you should be able to:

  • Choose state-aware modules instead of shell commands.
  • Explain changed status.
  • Use notify and handlers correctly.

One resource, one module intention

Modules are reusable units of automation. Builtin modules cover common resources such as files, templates, packages, services and users. Collections add content for many platforms and products.

Using the Fully Qualified Collection Name, such as ansible.builtin.template, makes the module source obvious and avoids ambiguity when collections contain similarly named plugins.

Handlers react to change

A handler is a special task triggered by notify. It runs only when a notifying task reports changed. This is ideal for operations such as restarting a service after its configuration file changes.

If three tasks notify the same handler, Ansible normally runs the handler once at the appropriate handler point rather than restarting the service three times.

changed should mean something

Accurate changed status is important because handlers, reporting and operational confidence depend on it. Avoid tasks that report changed every run when nothing actually changed.

Worked examples

See the idea in practice.

Template with handler

tasks:
  - name: Deploy nginx configuration
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
      owner: root
      group: root
      mode: '0644'
    notify: Restart nginx

handlers:
  - name: Restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted
  • The template task reports changed only when rendered content or managed attributes differ.
  • notify schedules the handler when a change occurs.
  • The restart is separated from the configuration task.

Inspect module documentation

ansible-doc ansible.builtin.template
ansible-doc ansible.builtin.service
  • ansible-doc shows arguments, notes and examples from installed content.
  • Consult module documentation rather than guessing parameter names.
Hands-on lab

Lab — Restart only when configuration changes

Goal: Deploy a managed nginx file and prove that the restart handler runs only when the file changes.

STEP 1

Create a template

# templates/index.html.j2
<h1>{{ inventory_hostname }}</h1>
<p>Managed by Ansible</p>
STEP 2

Add a deployment task

- name: Deploy web page
  ansible.builtin.template:
    src: templates/index.html.j2
    dest: /usr/share/nginx/html/index.html
    mode: '0644'
  notify: Restart nginx
STEP 3

Run twice

ansible-playbook -i inventory.ini web.yml
ansible-playbook -i inventory.ini web.yml
STEP 4

Modify template and run again

Change one line in the template. The template task should report changed and the handler should run.

Verify

  • Second unchanged run does not redeploy the same content.
  • Handler runs after a real template change.
  • Rendered content contains the managed host name.

Expected outcome

  • The service is not restarted unnecessarily on a clean rerun.

If it fails

  • If the handler never runs, confirm the notifying task actually reports changed and the handler name matches exactly.
  • If the template cannot be found, check the path relative to the playbook or role structure.
Real-world connection

Change-driven handlers reduce unnecessary service disruption during configuration management.

Avoid these traps

Common mistakes

  • Restarting a service unconditionally on every playbook run.
  • Using command or shell to manage a resource that has a dedicated module.
  • Using handler names inconsistently between notify and handlers.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1When does a notified handler normally run?

When a notifying task reports changed and execution reaches the handler point.

2Why is accurate changed reporting important?

It affects handlers, audit output and whether reruns are truly idempotent.

3How do you inspect installed module documentation?

Use ansible-doc with the module's FQCN.