Ansible Role Structure Builder

Generate the file tree and main.yml stubs for an Ansible role

Scaffold a complete Ansible role: directory tree plus starter tasks/main.yml, defaults/main.yml, vars/main.yml, handlers/main.yml and meta/main.yml. Matches the layout of ansible-galaxy role init.

What is the standard Ansible role directory layout?

A role has tasks, handlers, defaults, vars and meta directories, each with a main.yml, plus optional files and templates folders. This is exactly what ansible-galaxy role init produces, so other Ansible users immediately understand the structure.

The Ansible Role Structure Builder scaffolds a complete role: the standard directory tree plus ready-to-edit main.yml stubs for tasks, defaults, vars, handlers and meta. It mirrors what ansible-galaxy role init generates, so your role is instantly recognisable to anyone who works with Ansible.

How it works

An Ansible role is a fixed set of directories that the engine auto-loads by convention. tasks/main.yml is the entry point. defaults/main.yml and vars/main.yml hold variables at low and high precedence respectively. handlers/main.yml defines tasks that run only when notified — typically a service restart after a config change. meta/main.yml carries Galaxy metadata and role dependencies. Optional files/ and templates/ folders hold static assets and Jinja2 templates.

The tool normalises your role name to the snake_case form Galaxy expects, then emits each file pre-populated with a realistic example task, a notify/handler pair and platform metadata you can edit down to your real values.

Tips and notes

Keep overridable settings in defaults/ and internal constants in vars/. Because Git does not track empty directories, drop a .gitkeep into any files/ or templates/ folder you want committed.

A handler is wired up like this:

# tasks/main.yml
- name: Install required package
  ansible.builtin.package:
    name: "{{ my_role_package }}"
    state: present
  notify: Restart service

# handlers/main.yml
- name: Restart service
  ansible.builtin.service:
    name: example
    state: restarted

Run ansible-lint against the generated role before publishing to catch deprecated module names and missing name: keys.