Project Layout¶
What You'll Learn¶
- A production-grade repository structure, and why each piece is separated the way it is
- How environments (dev/staging/prod) stay isolated from each other by structure, not discipline alone
The Layout¶
ansible-project/
├── ansible.cfg
├── requirements.yml # pinned collection dependencies
├── requirements.txt # pinned Python dependencies (ansible-core, etc.)
├── inventories/
│ ├── dev/
│ │ ├── hosts.ini
│ │ └── group_vars/
│ ├── staging/
│ │ ├── hosts.ini
│ │ └── group_vars/
│ └── production/
│ ├── hosts.ini
│ └── group_vars/
├── group_vars/ # cross-environment defaults, if any
├── host_vars/
├── playbooks/
│ ├── site.yml
│ └── deploy.yml
├── roles/
│ └── nginx/
├── collections/ # locally installed, gitignored
├── library/ # project-local custom modules
├── plugins/
│ └── filter_plugins/
├── templates/ # only if not scoped inside a role
├── files/
├── molecule/ # role-level test scenarios
├── README.md
└── .ansible-lint
Why Environments Are Separate Directories, Not Just Variables¶
Separate inventory directories per environment mean a mistyped --limit or a missing -i flag cannot accidentally reach production — the wrong inventory simply doesn't contain those hosts. A single shared inventory with an env variable to distinguish dev from prod puts that same safety burden on every engineer remembering to pass the right flag correctly, every time.
What Belongs Where¶
| Directory | Contents |
|---|---|
inventories/<env>/ |
That environment's hosts and group_vars/host_vars |
roles/ |
Reusable, testable units — see Roles |
collections/ |
Installed dependencies, pinned via requirements.yml — gitignored, reinstalled by CI |
library/ |
Project-local custom modules not yet worth packaging as a collection |
molecule/ |
Per-role test scenarios — see Molecule Testing |
playbooks/ |
Entry points — site.yml, deploy.yml — kept thin, composed of roles |
Common Mistakes¶
- One shared inventory file with an
env:variable instead of separateinventories/<env>/directories — a single flag mistake can then target the wrong environment. - Committing
collections/to version control instead ofrequirements.yml— bloats the repo and drifts from what CI actually installs. - Playbooks that are hundreds of lines of raw tasks instead of thin entry points composed of roles.
Interview Questions¶
- Why structure inventories as separate directories per environment instead of one inventory with an environment variable?
- What belongs in
library/versus a proper collection, and when do you graduate from one to the other?
Next¶
Continue to ansible.cfg.