Roles & collections
Your playbook sets up a web server. Soon you'll want the same web server setup in another project, plus a database setup, plus a monitoring agent. Copy-pasting tasks between playbooks is how bugs get fixed in one place and not the other. A role packages everything for one job (tasks, handlers, templates, defaults) into a folder any playbook can use with one line. Collections are how roles and modules are shared with the world.
You will learn
- The standard role layout, made with
ansible-galaxy role init - Turning a playbook into a role, and the
TASK [role : name]output defaults/(easy to override) vsvars/(hard to override)- Collections and FQCNs:
ansible.builtin.,ansible.posix.,community.general. ansible-doc,ansible-galaxy collection listandrequirements.yml
What's in a role
ansible-galaxy role init --init-path roles web
roles/web/ ├── defaults/main.yml default values: the LOWEST priority, meant to be overridden ├── files/ plain files for the copy module ├── handlers/main.yml handlers (Restart Apache) ├── meta/main.yml author, license, and dependencies on other roles ├── tasks/main.yml the tasks: a plain LIST, no hosts: or play around it ├── templates/ .j2 templates. src: index.html.j2 is found here automatically ├── tests/ a tiny test playbook ├── vars/main.yml internal variables: high priority, not meant to be changed └── README.md what it does, and which variables you can set
Only tasks/main.yml is required. Delete the folders you don't use.
Playbook → role
Your whole playbook shrinks to this:
---
- name: Set up the web servers
hosts: web
become: true
roles:
- web
Ansible finds roles/web next to the playbook (or in ~/.ansible/roles and /etc/ansible/roles), runs its tasks first, then any tasks: in the play. The output labels them so you know where each task came from: TASK [web : Install Apache].
defaults vs vars
defaults/main.yml | vars/main.yml | |
|---|---|---|
| Priority | Lowest of all: group_vars, host_vars and play vars all beat it | High: beats group_vars and host_vars |
| For | Settings the user of the role is meant to change: site_title: "Welcome" | Internal constants the role needs, like a list of package names |
Put almost everything in defaults, and write them down in the role's README. That list is the role's “settings menu”.
Collections and FQCNs
Modules come in collections, named namespace.collection. The full name of a module is its FQCN (fully qualified collection name):
| FQCN | Comes with |
|---|---|
ansible.builtin.template, .package, .service… | ansible-core: always there |
ansible.posix.firewalld, .authorized_key | the ansible package, or ansible-galaxy collection install ansible.posix |
community.general.ufw, containers.podman.podman_container, amazon.aws.ec2_instance | the same, thousands of modules |
Short names (template:) still work, but the FQCN is unambiguous, so it's what linters ask for.
ansible-galaxy collection list # what's installed ansible-doc ansible.builtin.template # a module's manual, offline ansible-galaxy collection install -r requirements.yml # what a project needs (internet)
collections:
- name: ansible.posix
version: ">=1.5.0"
- name: community.generalCheck requirements.yml into git, so a new teammate (or your CI pipeline) gets exactly the same collections.
Practice: turn the playbook into a role 🧱
The project is where the last lesson ended. Make a web role, move the tasks, handlers and template into it, and slim site.yml down to five lines. The ready-made pieces are in examples/role/.
Quick check
1. A role's defaults/main.yml says site_title: "Welcome", and group_vars/web.yml says "CHT Tickets". Which wins?
✓ That's what makes a role reusable: sensible defaults, easy to override.
2. What goes in a role's tasks/main.yml?
✓ The play (hosts, become) lives in the playbook that USES the role.
3. What does ansible.posix.firewalld tell you that firewalld doesn't?
✓ FQCN = namespace.collection.module.