Ansible Role Directory Structure
This chapter covers the biggest conceptual shift in this entire course: files that load themselves, purely by being named and placed correctly, with nothing anywhere explicitly pointing at them.
The Standard Role Layout
roles/
myapp/
tasks/
main.yml
handlers/
main.yml
templates/
app.conf.j2
files/
static_file.txt
vars/
main.yml
defaults/
main.yml
meta/
main.ymltasks/main.yml: The Role’s Entry Point
The role’s actual task list — exactly the same task syntax used throughout this entire course, just living in this specific file instead of directly inside a play:
- name: Install myapp package
ansible.builtin.package:
name: myapp
state: present
- name: Deploy config
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
notify: Restart myapphandlers/main.yml: Automatically Available Handlers
Any handler defined here becomes available to be notified from within the role’s own tasks automatically — no special linking required:
- name: Restart myapp
ansible.builtin.systemd:
name: myapp
state: restartedtemplates/ And files/: No src: Path Needed
A genuinely convenient shift from everything covered so far: when a task inside a role references template: src: app.conf.j2, Ansible automatically looks inside this role’s own templates/ directory first — no relative or absolute path needed, unlike the careful path resolution this course covered for lookups and templates used directly in a standalone playbook. The same automatic resolution applies to files/ for copy’s src:.
vars/main.yml And defaults/main.yml: Two Kinds Of Variables
Both hold variables, but with a real, important precedence difference between them — covered in full in the next chapter. For now, just note their location: vars/main.yml and defaults/main.yml, both loaded automatically the same way tasks/main.yml is.
meta/main.yml: Role Metadata And Dependencies
Holds information about the role itself, and — genuinely more important — declared dependencies on other roles. Covered fully later in this section; for now, just its location: meta/main.yml.
The Big Shift: main.yml Is Loaded Automatically
This is worth sitting with directly, since it’s a real departure from everything this course has built up until now. Every single file reference covered so far — vars_files, import_tasks, a template’s src:, a lookup’s file path — required explicitly naming or pointing at that file, somewhere. Inside a role, a file named exactly main.yml, sitting in one of these standard directories, is loaded automatically, purely by its name and location. There’s no import_tasks: tasks/main.yml written anywhere inside the role, no vars_files: pointing at vars/main.yml — simply placing a correctly-named file in the correct directory is enough.
A Realistic Skeleton
Bringing tasks/, handlers/, and templates/ together into one coherent role, with vars/, defaults/, and meta/ left minimal for now — full treatment of each comes in upcoming chapters:
roles/
myapp/
tasks/
main.yml # Install package, deploy template, notify handler
handlers/
main.yml # Restart myapp
templates/
app.conf.j2 # The actual config template
defaults/
main.yml # (covered next chapter)
vars/
main.yml # (covered next chapter)
meta/
main.yml # (covered later in this section)Best Practices
- Always name the file
main.ymlinside each of these standard subdirectories — this exact name is what makes automatic loading work; anything else is silently never picked up. - Keep a role focused on one coherent piece of functionality, like “deploy myapp,” rather than a grab-bag of loosely related tasks.
- Rely on the automatic
templates//files/resolution — don’t write full paths to these locations from within a role’s own tasks; the whole point is that you don’t have to.