AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

What Are Ansible Roles: Complete Guide to Role Structure (2026)

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible roles. Understand role structure, create reusable roles, use defaults, handlers, templates, and organize playbooks with roles.

Ansible roles are a key feature that simplify and organize complex playbooks, making them reusable and scalable. This article explores what roles are, their structure, and how to use them effectively in your automation workflows.

What Are Ansible Roles?

Roles in Ansible are a way to organize playbooks into reusable components. They allow you to define specific tasks, variables, files, templates, and handlers in a structured format. By using roles, you can easily apply the same configuration across multiple playbooks or projects.

Why Use Roles?

  • Code Reusability: Write once and reuse in multiple playbooks.
  • Simplification: Break down large playbooks into smaller, manageable parts.
  • Consistency: Maintain uniformity across projects.
  • Collaboration: Facilitate teamwork by modularizing tasks.

Structure of an Ansible Role

Ansible roles follow a predefined directory structure, which ensures clarity and organization. Below is the typical structure:

roles/
└── example_role/
    ├── tasks/           # Task definitions
    │   └── main.yml
    ├── handlers/        # Handlers triggered by tasks
    │   └── main.yml
    ├── templates/       # Jinja2 templates for configuration files
    ├── files/           # Static files to be copied
    ├── vars/            # Variables specific to the role
    │   └── main.yml
    ├── defaults/        # Default variable values
    │   └── main.yml
    ├── meta/            # Metadata about the role (dependencies, author info)
    │   └── main.yml
    └── README.md        # Documentation about the role

Key Components:

  • tasks/main.yml: Contains the primary tasks for the role.
  • handlers/main.yml: Defines handlers to be triggered by tasks.
  • vars/main.yml: Variables with higher precedence.
  • defaults/main.yml: Default variables with the lowest precedence.
  • templates/: Stores Jinja2 templates for dynamic configurations.
  • files/: Holds static files to be copied to target systems.

Creating an Ansible Role

To create a role, use the ansible-galaxy command:

ansible-galaxy init my_role

This command creates the necessary directory structure for the role.

Example Task in a Role

Here’s an example of a task to install Nginx in the tasks/main.yml file:

- name: Install Nginx
  apt:
    name: nginx
    state: present
  become: yes

Using the Role in a Playbook

Once the role is defined, it can be included in a playbook:

- hosts: all
  roles:
    - role: my_role

See also: Ansible troubleshooting - Error sanity

Best Practices for Ansible Roles

  1. Use Meaningful Names: Name roles descriptively to indicate their purpose.
  2. Organize Variables: Use defaults/ for default values and vars/ for overrides.
  3. Document Roles: Include a README.md to explain the role's functionality.
  4. Leverage Ansible Galaxy: Share and reuse roles via Ansible Galaxy.

Benefits of Ansible Roles

  • Scalability: Manage large, complex environments easily.
  • Flexibility: Modularize configurations for varied requirements.
  • Maintainability: Simplify updates and troubleshooting.

Conclusion

Ansible roles are a cornerstone of efficient automation, enabling structured, reusable, and scalable playbooks. By adopting roles, you can streamline your workflows and enhance collaboration in DevOps teams.

Explore More About Ansible Roles in Ansible Galaxy

Role Directory Structure

roles/
  webserver/
    tasks/main.yml       # Main task list
    handlers/main.yml    # Handler definitions
    templates/           # Jinja2 templates
    files/               # Static files
    vars/main.yml        # Role variables (high priority)
    defaults/main.yml    # Default variables (low priority)
    meta/main.yml        # Dependencies, Galaxy metadata
    tests/               # Test playbooks

See also: Ansible Molecule: Test Roles & Collections in Containers (Guide)

Create a Role

ansible-galaxy role init webserver

Example Role

# roles/webserver/defaults/main.yml
webserver_port: 80
webserver_docroot: /var/www/html

# roles/webserver/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: restart nginx

- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

# roles/webserver/handlers/main.yml
- name: restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

See also: Ansible Role Input Validation with validate_argument_spec

Use Roles in Playbooks

roles keyword

- hosts: webservers
  become: true
  roles:
    - webserver
    - { role: database, db_port: 5432 }
    - role: monitoring
      when: enable_monitoring | default(true)

include_role (dynamic)

- hosts: all
  tasks:
    - name: Include role conditionally
      include_role:
        name: webserver
      when: "'webservers' in group_names"

import_role (static)

- hosts: all
  tasks:
    - import_role:
        name: common
        tasks_from: security  # Run specific task file

Role Dependencies

# roles/webapp/meta/main.yml
dependencies:
  - role: common
  - role: webserver
    webserver_port: 8080

Install from Galaxy

# Install single role
ansible-galaxy role install geerlingguy.docker

# Install from requirements
ansible-galaxy role install -r requirements.yml
# requirements.yml
roles:
  - name: geerlingguy.docker
    version: "7.1.0"
  - name: geerlingguy.nginx

Roles vs Playbooks vs Collections

ConceptScopeSharing
PlaybookComplete automationProject-specific
RoleReusable task bundleGalaxy / Git
CollectionRoles + modules + pluginsGalaxy / Automation Hub

FAQ

When should I use a role vs inline tasks?

Use roles when tasks are reusable across projects or complex enough to benefit from organized structure. Simple one-off tasks can stay inline.

What's the variable precedence between defaults and vars?

defaults/main.yml has lowest priority (easily overridden). vars/main.yml has higher priority (harder to override). Use defaults for user-configurable values.

Can I run only part of a role?

- import_role:
    name: webserver
    tasks_from: configure  # Runs tasks/configure.yml

Role Structure

roles/webserver/
├── defaults/main.yml     # Default variables (lowest priority)
├── vars/main.yml         # Role variables (higher priority)
├── tasks/main.yml        # Main task list
├── handlers/main.yml     # Handlers (triggered by notify)
├── templates/            # Jinja2 templates
│   └── nginx.conf.j2
├── files/                # Static files
│   └── index.html
├── meta/main.yml         # Dependencies, metadata
├── tests/                # Test playbooks
└── README.md

Create a Role

ansible-galaxy role init webserver

Use in Playbook

# Simple
- hosts: webservers
  roles:
    - webserver

# With variables
- hosts: webservers
  roles:
    - role: webserver
      vars:
        http_port: 8080
        server_name: example.com

# Conditional
- hosts: all
  roles:
    - role: webserver
      when: install_web | default(true)

defaults/main.yml

# Lowest priority — users can easily override
http_port: 80
server_name: localhost
document_root: /var/www/html
max_connections: 1024
enable_ssl: false

tasks/main.yml

---
- name: Install nginx
  ansible.builtin.apt:
    name: nginx
    state: present
  become: true

- name: Deploy configuration
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx
  become: true

- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true
  become: true

handlers/main.yml

---
- name: restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted
  become: true

- name: reload nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded
  become: true

meta/main.yml

---
galaxy_info:
  author: Your Name
  description: Nginx web server role
  license: MIT
  min_ansible_version: "2.15"
  platforms:
    - name: Ubuntu
      versions: [jammy, noble]
    - name: Debian
      versions: [bookworm]
dependencies:
  - role: common
  - role: firewall
    vars:
      open_ports: [80, 443]

Include Tasks from Role

# In playbook (without full role)
- include_role:
    name: webserver
    tasks_from: ssl-setup  # runs tasks/ssl-setup.yml

Role Dependencies

# meta/main.yml
dependencies:
  - role: common
  - role: security_baseline
  - role: monitoring
    vars:
      monitor_port: 9090

Organizing Roles

project/
├── ansible.cfg
├── inventory.yml
├── site.yml
├── webservers.yml
├── dbservers.yml
├── group_vars/
├── host_vars/
└── roles/
    ├── common/         # Shared baseline
    ├── webserver/      # Nginx/Apache
    ├── database/       # PostgreSQL/MySQL
    ├── monitoring/     # Prometheus/Grafana
    └── security/       # Hardening

Roles vs include_tasks vs import_tasks

FeatureRolesinclude_tasksimport_tasks
ReusabilityHighMediumMedium
StructureFull directorySingle fileSingle file
Variablesdefaults + varsNoneNone
HandlersYesNoNo
DependenciesYesNoNo
GalaxyYesNoNo

FAQ

When should I use a role vs a playbook?

Roles for reusable, shareable automation (install nginx, configure database). Playbooks for orchestration (deploy full stack, run maintenance).

Can I override role defaults?

Yes — set variables in playbook vars, group_vars, host_vars, or extra vars. Role defaults have the lowest priority.

How do I share roles?

Publish to Ansible Galaxy or a private Automation Hub. Or use Git repositories as role sources in requirements.yml.

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home