unit 2 · Setup
ansible.cfg & config precedence
Four places, first one wins
you may want to read 5 · Installing a control node first — but nothing is locked
tl;dr
- Every run reads ONE config file: ANSIBLE_CONFIG → ./ansible.cfg → ~/.ansible.cfg → /etc/ansible/ansible.cfg.
- First file found wins — the search stops there. Nothing merges.
- Best practice: a project-root ansible.cfg committed to Git, so everyone runs with identical settings.
why it matters Two engineers run the same command and get different inventories, users and behaviour because different ansible.cfg files won — until you know the search order, that looks like magic.
Lesson 5 left you with a working control node. Before pointing it at a real machine, know where Ansible gets its settings. The honest answer is “it depends on the directory you’re standing in” — and that catches people on day one.
Every command in the toolbox — ansible, ansible-playbook,
ansible-inventory — reads its defaults from a single INI file called
ansible.cfg. Which file? Ansible searches four places, in order, and
stops at the first one it finds:
- Whatever the
ANSIBLE_CONFIGenvironment variable points to ./ansible.cfg— the current working directory~/.ansible.cfg— your home directory/etc/ansible/ansible.cfg— the machine-wide fallback
First found wins. The search stops dead. Nothing merges. If a project
ships its own ansible.cfg and you run from inside it, your carefully tuned
~/.ansible.cfg contributes nothing.
Put it in the repo
That cwd slot at position 2 is the whole strategy. Best practice: a
project-root ansible.cfg, committed to Git. Everyone who clones the
repo and runs from its root gets identical behaviour — same inventory, same
parallelism, same paths — not whatever their laptop has in ~/.ansible.cfg.
It’s the first file in the standard repo layout you’ll meet in lesson 36.
Slot 1 is for runs that must ignore all of that. The environment variable outranks even the project file, so a CI job can force a known config no matter what the checkout contains:
ANSIBLE_CONFIG=/opt/ci/ansible.cfg ansible-playbook site.ymlWhat goes in it
A sensible starter — only settings you’ll actually touch early:
[defaults]
inventory = inventories/dev/ # default inventory (unit 3) — no -i flag on every run
remote_user = ansible # the user Ansible logs in to managed nodes as
forks = 20 # parallelism: how many hosts to work on at once
host_key_checking = False # lab convenience — leave SSH host-key checks on in prod
roles_path = roles # where this repo keeps its roles (lesson 24)Quick tour. inventory sets a default so nobody types -i on every run.
remote_user is the login account on the managed nodes.
forks caps how many hosts Ansible handles in parallel.
host_key_checking = False skips the interactive SSH host-key prompt —
fine for throwaway lab VMs, never for production.
Other settings live in the same file. You’ll meet each when its topic
arrives: collections_path (where installed collections go), become
(privilege escalation defaults), gathering and fact caching (lesson 17),
and stdout_callback, which swaps the run output format via a callback
plugin (lesson 14). Resist tuning them now — a small, boring config in Git
beats a clever one on your laptop.
When Ansible behaves differently on two machines — or in CI versus your
laptop — ask which config file won before anything else. Check the env
var, then look for an ansible.cfg in the
directory you ran from. Nine times out of ten, that’s the whole mystery.
Next lesson: your first ad-hoc command.
at work, this sounds like
- “Just run it from the repo root — the ansible.cfg handles it.”
- The project ships its own config file; running from that directory picks it up, so the inventory and other defaults are preset.
- “Bump the forks if it feels slow.”
- Raise the parallelism setting in ansible.cfg so Ansible works on more hosts simultaneously.
self-check — recall, not a test
1 Name the four places Ansible looks for its config, in order.
2 Why commit an ansible.cfg at the project root?
3 Does this precedence chain decide which value a variable ends up with?