Skip to content

Roles

First PublishedByAtif Alam

A role is a structured, reusable package of tasks, handlers, templates, files, and variables. Roles let you organize automation into modular, shareable units instead of putting everything in one large playbook.

roles/
nginx/
tasks/
main.yml # entry point for tasks
handlers/
main.yml # handlers (e.g. restart nginx)
templates/
nginx.conf.j2 # Jinja2 templates
files/
index.html # static files to copy
vars/
main.yml # role variables (high priority)
defaults/
main.yml # default variables (low priority, easily overridden)
meta/
main.yml # role metadata and dependencies
README.md

Only tasks/main.yml is required. All other directories are optional — include only what you need.

DirectoryPurpose
tasks/The actual work — install packages, copy files, configure services
handlers/Tasks triggered by notify (e.g. restart, reload)
templates/Jinja2 templates rendered with template module
files/Static files copied with copy module
vars/Variables with high precedence (hard to override)
defaults/Variables with low precedence (intended to be overridden by the user)
meta/Role metadata: author, license, dependencies

Create the directory structure yourself:

Terminal window
mkdir -p roles/nginx/{tasks,handlers,templates,defaults,files,meta}
Terminal window
ansible-galaxy role init roles/nginx

This creates the full skeleton with all directories and placeholder files.

# Easily overridden by the user
nginx_port: 80
nginx_server_name: localhost
nginx_worker_processes: auto
---
- name: Install nginx
apt:
name: nginx
state: present
update_cache: true
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
mode: "0644"
notify: Restart nginx
- name: Deploy site config
template:
src: default-site.conf.j2
dest: /etc/nginx/sites-available/default
notify: Reload nginx
- name: Ensure nginx is running
service:
name: nginx
state: started
enabled: true
---
- name: Restart nginx
service:
name: nginx
state: restarted
- name: Reload nginx
service:
name: nginx
state: reloaded
server {
listen {{ nginx_port }};
server_name {{ nginx_server_name }};
location / {
root /var/www/html;
index index.html;
}
}
site.yml
---
- name: Configure web servers
hosts: webservers
become: true
roles:
- nginx
- certbot
- myapp

Roles run before any tasks: in the same play.

roles:
- role: nginx
vars:
nginx_port: 8080
nginx_server_name: myapp.example.com

Include a role conditionally or within tasks:

tasks:
- name: Include monitoring role
include_role:
name: monitoring
when: enable_monitoring | default(true)

Imported at parse time (before execution). Conditions apply to every task in the role:

tasks:
- name: Import database role
import_role:
name: postgresql
tags: database
import_roleinclude_role
When resolvedParse time (static)Runtime (dynamic)
when applies toEvery task in the roleThe include itself
TagsAll role tasks inherit tagsOnly the include is tagged
LoopsNot supportedSupported

Use import_role by default; include_role when you need dynamic behavior (loops, conditional inclusion).

Ansible Galaxy is a community hub for sharing roles and collections.

Terminal window
ansible-galaxy role install geerlingguy.docker
ansible-galaxy role install geerlingguy.nginx

Installs to ~/.ansible/roles/ by default.

Pin roles and their versions:

requirements.yml
roles:
- name: geerlingguy.docker
version: "6.1.0"
- name: geerlingguy.nginx
version: "3.2.0"
- name: my-org.custom-role
src: git+https://github.com/my-org/custom-role.git
version: v1.0.0
Terminal window
ansible-galaxy role install -r requirements.yml

Modern Ansible packages roles and modules into collections:

Terminal window
ansible-galaxy collection install amazon.aws
ansible-galaxy collection install community.docker

Collections are the preferred distribution method for new content.

In meta/main.yml, declare roles that must run before yours:

roles/myapp/meta/main.yml
---
dependencies:
- role: nginx
vars:
nginx_port: 8080
- role: postgresql

When you use the myapp role, Ansible automatically runs nginx and postgresql first.

Dependencies are deduplicated — if two roles both depend on nginx, it runs only once (unless allow_duplicates: true is set).

  • A role is a directory with tasks/, handlers/, templates/, defaults/, etc.
  • Put user-overridable variables in defaults/ (low priority); internal variables in vars/ (high priority).
  • Use ansible-galaxy role init to scaffold, ansible-galaxy role install to pull community roles.
  • Pin role versions in requirements.yml for reproducible builds.
  • Use import_role by default; include_role for dynamic/conditional inclusion.
  • Declare dependencies in meta/main.yml so prerequisite roles run automatically.