Skip to content
CloudOps
All prompts
AI for Infrastructure as Code Difficulty: Intermediate ClaudeChatGPT

Ansible Roles Structure Best Practices Prompt

Design Ansible roles — defaults vs vars, meta dependencies, role parameters, tags, idempotency.

Target user
Ansible engineers building reusable roles
Difficulty
Intermediate
Tools
Claude, ChatGPT

The prompt

You are a senior Ansible engineer who has built and maintained roles used across many projects — focused, parameterized, well-tested.

I will provide:
- The role purpose
- Current structure
- Goal (design new / refactor)

Your job:

1. **Standard role structure**:
   ```
   roles/myrole/
   ├── defaults/main.yml      # overridable vars (LOW precedence)
   ├── vars/main.yml          # role internals (HIGH precedence)
   ├── tasks/main.yml         # tasks
   ├── handlers/main.yml      # handlers
   ├── templates/             # Jinja2 templates
   ├── files/                 # static files
   ├── meta/main.yml          # metadata, dependencies
   └── README.md              # documentation
   ```
2. **For defaults/main.yml**:
   - Variables meant to be overridden
   - Document each with comment
   - Sensible defaults
3. **For vars/main.yml**:
   - Internal vars
   - Higher precedence (hard to override)
   - Avoid; prefer defaults
4. **For meta/main.yml**:
   - galaxy_info (author, description, license)
   - dependencies on other roles
   - supported platforms
5. **For dependencies**:
   - `dependencies:` list with role and vars
   - Auto-run before this role
   - Use sparingly
6. **For tags**:
   - Tag tasks for selective run
   - `--tags`, `--skip-tags`
   - Document tags in README
7. **For parameters**:
   - Pass vars at role include
   - `roles: - role: myrole vars: {x: y}`
8. **For role design principles**:
   - Single responsibility
   - Parameterized
   - Idempotent
   - Documented
   - Tested

Mark DESTRUCTIVE: putting sensitive in defaults (readable), tight role dependencies (couples), vars/main.yml hiding intended overrides.

---

Role purpose: [DESCRIBE]
Current structure: [DESCRIBE]

Why this prompt works

Role structure determines reusability. This prompt walks design.

How to use it

  1. Single responsibility.
  2. defaults for overridable.
  3. Test with Molecule.
  4. Document in README.

Standard role layout

roles/web/
├── defaults/
│   └── main.yml          # web_port: 80, web_workers: 4
├── vars/
│   └── main.yml          # internal: web_install_path: /opt/web
├── tasks/
│   ├── main.yml
│   ├── install.yml
│   ├── configure.yml
│   └── service.yml
├── handlers/
│   └── main.yml
├── templates/
│   └── nginx.conf.j2
├── files/
│   └── ssl-params.conf
├── meta/
│   └── main.yml
├── molecule/
│   └── default/
│       ├── molecule.yml
│       ├── converge.yml
│       └── verify.yml
└── README.md

Patterns

tasks/main.yml as orchestrator

- name: Install
  import_tasks: install.yml
  tags: [install]

- name: Configure
  import_tasks: configure.yml
  tags: [configure]

- name: Start service
  import_tasks: service.yml
  tags: [service]

defaults/main.yml

---
# Web server settings (overridable)
web_port: 80
web_workers: 4
web_log_level: info
web_ssl_enabled: false
web_ssl_cert: /etc/ssl/certs/web.crt
web_ssl_key: /etc/ssl/private/web.key

# User configuration
web_user: webuser
web_group: webgroup

meta/main.yml

galaxy_info:
  author: Platform Team
  description: Web server (nginx) deployment
  company: Example Inc
  license: MIT
  min_ansible_version: 2.12
  platforms:
  - name: Ubuntu
    versions: [22.04, 24.04]
  - name: EL
    versions: [9]
  galaxy_tags:
    - web
    - nginx
    - production

dependencies:
- role: common
- role: firewall
  vars:
    firewall_ports: ['80/tcp', '443/tcp']

Tag usage

- name: Install nginx
  package:
    name: nginx
  tags: [install, packages]

- name: Configure nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  tags: [config]
  notify: restart nginx

Run subset:

ansible-playbook site.yml --tags config

Role usage in playbook

- hosts: webservers
  roles:
  - role: web
    vars:
      web_workers: "{{ ansible_processor_vcpus }}"
      web_ssl_enabled: true
  - role: monitoring
    vars:
      monitoring_endpoint: "{{ web_port }}/metrics"

Common findings this catches

  • Role too big → split into focused roles.
  • defaults hiding secrets → move to vault.
  • vars/main.yml overrides confusing → switch to defaults.
  • No README → adopt template.
  • Tight dep chain → loosen.
  • No tests → add Molecule.
  • Hardcoded distro paths → use ansible_facts.

When to escalate

  • Role library design — coordinate.
  • Collection migration — strategic.
  • Cross-role conflicts — review.

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.