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.

See also: Ansible troubleshooting - Error sanity

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 Molecule: Test Roles & Collections in Containers (Guide)

Best Practices for Ansible Roles

Use Meaningful Names: Name roles descriptively to indicate their purpose. Organize Variables: Use defaults/ for default values and vars/ for overrides. Document Roles: Include a README.md to explain the role's functionality. 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.

See also: Ansible Collections: What They Are & How to Use Them (2026 Guide)

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

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

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

| Concept | Scope | Sharing | |---------|-------|---------| | Playbook | Complete automation | Project-specific | | Role | Reusable task bundle | Galaxy / Git | | Collection | Roles + modules + plugins | Galaxy / 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

| Feature | Roles | include_tasks | import_tasks | |---------|-------|---------------|--------------| | Reusability | High | Medium | Medium | | Structure | Full directory | Single file | Single file | | Variables | defaults + vars | None | None | | Handlers | Yes | No | No | | Dependencies | Yes | No | No | | Galaxy | Yes | No | No |

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.

Related Articles

discovering content via Ansible Galaxytemplate lookups in Ansibleusing handlers in Ansible playbooksbecome_user and become_method in Ansiblethe Ansible Nginx reference

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home