Modular Architecture: Reusable Roles & Ansible Galaxy

Master Ansible Roles directory structure, generating roles with ansible-galaxy, role dependencies, meta configuration, and Red Hat 1-Git-repo-per-role standards.

advanced 25 min lesson hands-on task included

As enterprise automation grows to thousands of lines of YAML, placing all tasks, variables, handlers, and templates in single files creates unmaintainable monoliths.

Ansible Roles provide a standardized, modular directory structure that encapsulates tasks, variables, handlers, templates, and files into clean, reusable automation packages.


Topic 1: Standard Ansible Role Directory Layout

Standard Ansible Role Directory Layout: Encapsulating tasks, handlers, vars, defaults, templates, and meta into modular packages.

When you generate a role using ansible-galaxy init roles/my_role, Ansible creates a standardized directory tree:

roles/nginx_server/
├── defaults/
│   └── main.yml        # Lowest-precedence default variables (users CAN override)
├── vars/
│   └── main.yml        # High-precedence internal role constants (users SHOULD NOT override)
├── tasks/
│   └── main.yml        # Core execution tasks (can include sub-task files)
├── handlers/
│   └── main.yml        # Service notification handlers
├── templates/
│   └── nginx.conf.j2   # Jinja2 template files (referenced without directory path)
├── files/
│   └── index.html      # Static files to copy (referenced without directory path)
├── meta/
│   └── main.yml        # Role metadata, author info, and role dependencies
└── README.md           # Documentation for role usage

[!NOTE] Directory Auto-Discovery: When a role executes, Ansible automatically searches inside the role’s templates/ folder for template tasks and files/ folder for copy tasks. You do not write relative paths like src: roles/nginx_server/templates/nginx.conf.j2 — write src: nginx.conf.j2 directly!


Topic 2: Consuming Roles in Playbooks

You can invoke roles in playbooks using three primary methods:

1. Classic roles: Directive (Static Loading at Play Start)

The standard method to apply roles to host groups:

---
- name: Deploy Production Web Tier
  hosts: webservers
  become: true
  roles:
    - role: common_base
    - role: nginx_server
      vars:
        nginx_http_port: 8080    # Overrides role defaults/main.yml

2. Dynamic include_role (Evaluated at Runtime)

Loads a role dynamically inside a task list based on runtime conditionals:

tasks:
  - name: Conditionally load database tuning role
    ansible.builtin.include_role:
      name: postgresql_tuning
    when: db_performance_mode == "high"

3. Static import_role (Parsed at Playbook Pre-processing)

Imports a role statically before playbook execution begins:

tasks:
  - name: Import security compliance role
    ansible.builtin.import_role:
      name: rhel_hardening

Topic 3: Role Dependencies (meta/main.yml)

Roles can declare dependencies on other roles inside meta/main.yml. When the parent role runs, Ansible automatically executes all dependent roles first:

# roles/app_server/meta/main.yml
---
galaxy_info:
  author: DevOps Team
  description: Application Server Role
  license: MIT
  min_ansible_version: "2.14"

dependencies:
  - role: common_security
  - role: java_runtime
    vars:
      java_version: "17"

Topic 4: Ansible Galaxy & Requirements Management (requirements.yml)

Ansible Galaxy is the public community hub for sharing Ansible Roles and Collections.

  • Installing Roles via CLI: ansible-galaxy install geerlingguy.nginx -p ./roles
  • Managing Project Dependencies (roles/requirements.yml): Commit a requirements.yml file to version control listing all external role dependencies and pinned Git tags:
# roles/requirements.yml
roles:
  # Role from Ansible Galaxy community hub
  - name: geerlingguy.nginx
    src: geerlingguy.nginx
    version: 3.2.0

  # Role from private corporate Git repository
  - name: internal.security_hardening
    src: git@github.com:myorg/ansible-role-security.git
    scm: git
    version: v1.4.0
# Install all required roles into project roles directory
ansible-galaxy install -r roles/requirements.yml -p ./roles

[!TIP] Red Hat Best Practice: One Git Repository Per Role: In enterprise teams, place each role into its own dedicated Git repository. Use requirements.yml to pull specific tagged versions into playbooks, guaranteeing auditable and repeatable deployments across environments.


Common mistake: Writing a role that reaches into another role’s internal variables, or that only works when called in a specific order. It stops being reusable the first time somebody calls it on its own. Everything a role needs belongs in defaults/main.yml as a documented interface, and anything it truly requires belongs in meta/main.yml as a dependency.