Role Structure¶
What You'll Learn¶
- The standard role directory layout
- What loads automatically just from being in the right place, with no explicit
include_vars - How to scaffold one with
ansible-galaxy role init
The Standard Layout¶
myrole/
├── tasks/
│ └── main.yml # the role's task list
├── handlers/
│ └── main.yml # handlers this role's tasks can notify
├── defaults/
│ └── main.yml # lowest-precedence, freely overridable variables
├── vars/
│ └── main.yml # higher-precedence, role-internal variables
├── files/ # static files served by copy, etc.
├── templates/ # Jinja2 templates served by template
├── meta/
│ └── main.yml # role metadata, Galaxy info, dependencies
└── README.md
Scaffold it instead of building by hand:
What Auto-Wires, With No Extra Configuration¶
Simply listing myrole under roles: automatically:
- runs
tasks/main.yml - makes
handlers/main.ymlnotifiable by any task in the role - loads
defaults/main.ymlandvars/main.yml— noinclude_varsneeded - makes
files/andtemplates/the default search path forcopy/templatetasks inside this role's ownsrc:references
defaults/ vs. vars/ — the Role's Public Interface¶
defaults/main.yml is the role's public interface — the lowest-precedence source (see Variable Precedence), meant to be freely overridden by anyone consuming the role. vars/main.yml is higher-precedence and meant for values that are genuinely internal to how the role works, not something a consumer should typically need to change.
meta/main.yml¶
meta/main.yml
galaxy_info:
author: your-team
description: Installs and configures nginx
min_ansible_version: "2.15"
platforms:
- name: Ubuntu
versions: [jammy, noble]
dependencies:
- role: firewall
vars:
firewall_allowed_ports: [80, 443]
dependencies: pulls in another role automatically before this one runs — even for internal-only roles, an accurate meta/main.yml documents platform support and requirements instead of leaving them as tribal knowledge.
Common Mistakes¶
- Putting environment-specific values in
vars/main.ymlinstead ofdefaults/main.yml, making the role hard to reuse across projects without editing its internals. - Building a giant role that tries to do everything (install nginx and manage the database and configure the firewall) instead of composing several focused roles.
- Missing
meta/main.ymldependency declarations, so the role only works correctly if included in a specific, undocumented order. - Deeply nested role dependencies without
allow_duplicates: no, causing the same dependency role to run more than once unintentionally.
Interview Questions¶
- What is the standard directory structure of an Ansible role?
- What's the practical difference between
defaults/main.ymlandvars/main.yml? - How do role dependencies in
meta/main.ymlwork, and what's the risk if not guarded correctly?
Next¶
Continue to Role Variables and Interfaces.