Ansible Project Structure
Standard Ansible project layout with 21 explained components: inventory (production/staging), group_vars (all.yml/webservers.yml), host_vars (server1.yml), roles (common/webserver/database), playbooks (site.yml/web.yml/db.yml), templates (Jinja2), files (static assets), ansible.cfg, requirements.yml.
Overview
Ansible project layout
A well-structured Ansible project is self-documenting, easy to test, and scales to hundreds of hosts without becoming unmanageable. The standard layout separates concerns: inventory (where), variables (what values), roles (how) and playbooks (when and for whom).
Inventory: where
The project root, ansible-project/, is usually a Git repository. inventory/ defines target hosts and groups them logically.
- inventory/production — The production hosts file (INI or YAML); lists hostnames/IPs and group memberships
- inventory/staging — Staging/test hosts; same structure, different IPs
Variables: what values
- group_vars/all.yml — Every host in every group — ansible_user, common package lists, org-wide settings
- group_vars/webservers.yml — Hosts in the [webservers] group — http_port, nginx_version, ssl settings
- host_vars/server1.yml — server1 only — Unique IP, custom listen port, host-specific cert paths
Roles and playbooks: how, when and for whom
- roles/common/ — Baseline on every host: OS updates, users, SSH hardening, monitoring agents
- roles/webserver/ — Nginx/Apache install, configuration templates, service management
- roles/database/ — MySQL/PostgreSQL install, DB/user creation, backup config
- playbooks/site.yml — Master playbook; imports web.yml and db.yml and applies the full stack
- playbooks/web.yml — Runs webserver and common roles against [webservers]
- playbooks/db.yml — Runs database and common roles against [databases]
Supporting files
- templates/ — Jinja2 templates (.j2) rendered with variable values before copying, for example nginx.conf.j2 with {{ server_name }} and {{ http_port }}
- files/ — Static files copied unchanged, for example CA certificates, pre-built binaries
- ansible.cfg — Project config overriding /etc/ansible/ansible.cfg: inventory path, remote_user, private_key_file, roles_path, host_key_checking=False
- requirements.yml — External roles and collections; ansible-galaxy install -r requirements.yml installs everything
> [!TIP] Pin versions in requirements.yml to prevent unexpected upgrades.
Key concepts
- Variable precedence
- Ansible merges variables from many sources. Precedence order (lowest to highest): role defaults → inventory group_vars/all → inventory group_vars/ → inventory host_vars → playbook group_vars → playbook host_vars → task vars → extra vars (-e). Host vars override group vars; -e overrides everything.
- ansible.cfg
- Project-level configuration file. Ansible searches: ANSIBLE_CONFIG env var → ./ansible.cfg → ~/.ansible.cfg → /etc/ansible/ansible.cfg. Having ansible.cfg in the project root ties configuration to the project, avoiding surprises from system-wide settings.
- Jinja2 templates
- Ansible uses the Jinja2 templating engine. Variables are referenced with {{ variable_name }}. Conditionals: {% if condition %} ... {% endif %}. Loops: {% for item in list %} ... {% endfor %}. Templates in templates/ are rendered and deployed with the template module.
- Dynamic inventory
- Instead of static host files, inventory can be a Python script or plugin that queries a source of truth (AWS EC2, GCP, VMware, Netbox). Returns JSON with host groups and variables. Essential for cloud environments where hosts change dynamically.
- requirements.yml
- Declares external dependencies. Can list both collections and roles: --- collections: - name: amazon.aws version: ">=5.0.0" - name: community.general roles: - name: geerlingguy.nginx version: "3.2.0"
When to use it
- Starting any new Ansible project — use this structure from day one
- Onboarding team members — the standard layout is self-explanatory
- Scaling a monolithic playbook that has outgrown a single file
- Setting up CI/CD for infrastructure automation (test staging, then production)
- Preparing for Red Hat RHCE/EX294 exam — this structure is the exam standard
Interview questions
- Explain Ansible variable precedence and where you would define each type of variable.
Sign up free to read the full topic
More DevOps topics
Start free on Cariara · Coding problems · System design studio