Roles are how Ansible code stays organised and reusable beyond a single playbook.
A role is a directory with a fixed structure that Ansible loads automatically:
tasks/main.yml: the entry point,handlers/main.yml,templates/,files/(found without paths),defaults/main.yml: default variables, the lowest precedence: the role's public, overridable interface,vars/main.yml: internal variables with high precedence; not meant to be overridden,meta/main.yml: metadata and dependencies;meta/argument_specs.ymlvalidates role inputs.
ansible-galaxy role init roles/nginx scaffolds it.
Using roles:
roles:in a play runs them before the play'stasks.ansible.builtin.import_role(static, resolved at parse time) orinclude_role(dynamic, at run time, can be looped or conditional) inside tasks.- Similarly
import_tasksvsinclude_tasksfor task files.
Design tips: one role per component (nginx, postgres, app), prefixed variable names (nginx_worker_processes) to avoid collisions, sensible defaults for everything, and no hard-coded hostnames. Keep site-specific values in inventory group_vars.
A typical project: ansible.cfg, inventory/ (with group_vars), site.yml importing per-tier playbooks (webservers.yml), roles/, and requirements.yml for external roles and collections.
Example
# roles/nginx/defaults/main.yml
nginx_worker_processes: auto
nginx_sites: []
# roles/nginx/tasks/main.yml
- name: Install nginx
ansible.builtin.package: {name: nginx, state: present}
- name: Configure nginx
ansible.builtin.template: {src: nginx.conf.j2, dest: /etc/nginx/nginx.conf}
notify: Reload nginx
# roles/nginx/handlers/main.yml
- name: Reload nginx
ansible.builtin.service: {name: nginx, state: reloaded}
# webservers.yml
- name: Web tier
hosts: web
become: true
roles:
- role: nginx
vars: {nginx_worker_processes: 4}Remember
- Fixed layout: tasks, handlers, templates, files, defaults, vars, meta
- defaults = overridable interface; vars = internal
- import_* is static, include_* is dynamic
Watch out for
- Putting tunable settings in vars/main.yml, where inventory variables can't override them.