Skip to content
Commitpedia
Log in Join & edit

Ansible concepts: inventory, modules, playbooks, idempotency and roles

Ansible configures many servers over SSH from one control machine. Learn the core pieces: inventory, modules, tasks, playbooks, roles, and why runs are safe to repeat.

Not checked by a trusted editor yet Last edited Outdated?

Edit history of Ansible concepts: inventory, modules, playbooks, idempotency and roles: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
3 min

Ansible is an automation tool that configures servers, installs software and deploys applications. You describe what you want in YAML files, and Ansible connects to each machine, usually over SSH, and makes it so. There is no agent to install on the servers you manage.

Control node and managed nodes

The control node is the machine where you run the Ansible commands: your laptop, a jump host or a CI runner. It must be Linux or macOS; the docs state that Windows without WSL is not supported as a control node. Managed nodes (also called hosts) are the servers you configure. They need SSH access for a user that can log in, and Python, because most modules are Python code that Ansible copies to the host and runs there.

pipx install --include-deps ansible
# or the minimal engine only:
pipx install ansible-core

Inventory: which machines

The inventory lists your managed nodes and groups them. A group lets you target many hosts at once and attach variables to all of them. Inventory can be a simple INI or YAML file, or a dynamic source such as a cloud API.

[web]
192.0.2.10
192.0.2.11

[db]
db1.example.com ansible_user=admin
ansible-inventory -i inventory.ini --list
ansible web -m ping -i inventory.ini

A successful ping ends with "ping": "pong" for each host. This is not an ICMP ping: it proves that Ansible can log in over SSH and run Python on the node.

Modules and tasks: what to do

A module is a unit of work such as installing a package (ansible.builtin.apt, ansible.builtin.dnf), copying a file (ansible.builtin.copy), rendering a template (ansible.builtin.template) or managing a service (ansible.builtin.service). A task is one call to a module with its arguments. Modules are distributed in collections; the ones in ansible.builtin ship with ansible-core.

Playbooks and plays: in what order

A playbook is a YAML file containing one or more plays. Each play maps a group of hosts to an ordered list of tasks, plus optional variables and handlers.

---
- name: Make sure chrony is installed and running
  hosts: web
  become: true
  tasks:
    - name: Install chrony
      ansible.builtin.apt:
        name: chrony
        state: present

    - name: Start chrony and enable it at boot
      ansible.builtin.service:
        name: chrony
        state: started
        enabled: true

become: true turns on privilege escalation (sudo by default) so the tasks run as root. Run the playbook with ansible-playbook -i inventory.ini chrony.yml.

Idempotency: describe the state, not the steps

Notice that the tasks say state: present and state: started, not “run apt install”. Most modules first check whether the desired state already exists and change nothing if it does. Such modules are called idempotent: running the same playbook twice gives the same result, and the second run reports changed=0. That is what makes Ansible safe to re-run after a failure or on a schedule.

Not everything is idempotent. The command and shell modules run whatever you give them every time, so prefer a dedicated module when one exists, and test new playbooks with --check (dry run) first.

Handlers: react to changes

A handler is a task that runs only when another task reports a change and notifies it, for example “reload nginx after its config file changed”. By default notified handlers run once, at the end of the play.

Roles: reusable bundles

When a playbook grows, you split it into roles. A role is a folder with a fixed layout that bundles tasks, handlers, templates, files and default variables for one job, such as “webserver” or “postgres”.

roles/webserver/
  tasks/main.yml      # the task list
  handlers/main.yml   # handlers
  templates/          # Jinja2 templates (.j2)
  files/              # static files
  defaults/main.yml   # low-precedence default variables
  vars/main.yml       # high-precedence role variables
  meta/main.yml       # dependencies and metadata
---
- hosts: web
  become: true
  roles:
    - common
    - webserver

Ansible looks for roles in a roles/ folder next to the playbook and in the configured roles_path. Shared roles and collections are published on Ansible Galaxy.

Official documentation

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

Repos in the wild

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Commitpedia +4,260 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?