unit 2 · Setup

ansible.cfg & config precedence

Four places, first one wins

essential · 6 min · linux + windows

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 you point it at a real machine, you need to know where Ansible gets its settings — because 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 this order, and stops at the first one it finds:

  1. Whatever the ANSIBLE_CONFIG environment variable points to
  2. ./ansible.cfg — the current working directory
  3. ~/.ansible.cfg — your home directory
  4. /etc/ansible/ansible.cfg — the machine-wide fallback

First found wins, and 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 exactly nothing to that run.

Put it in the repo

That cwd slot at position 2 is the whole strategy. The best practice is 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 — instead of whatever their laptop happens to have in ~/.ansible.cfg. It’s the first file in the standard repo layout you’ll meet in lesson 36.

Slot 1 exists for the runs that must ignore all of that. Because the environment variable outranks even the project file, a CI job can force a known config no matter what the checkout contains:

ANSIBLE_CONFIG=/opt/ci/ansible.cfg ansible-playbook site.yml
The env var beats every file — useful in CI

What goes in it

A sensible starter, using 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)
A project-root ansible.cfg, committed to Git

Quick tour: inventory sets a default so nobody has to remember an -i flag; 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 against throwaway lab VMs, not something to ship to production.

Other settings live in this same file and you’ll meet each one 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 the urge to tune them now — a small, boring config that lives in Git beats a clever one that lives on your laptop.

One habit closes this lesson: when Ansible behaves differently on two machines — or in CI versus your laptop — ask which config file won before you ask 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, the config starts paying rent: 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. 1 Name the four places Ansible looks for its config, in order.

  2. 2 Why commit an ansible.cfg at the project root?

  3. 3 Does this precedence chain decide which value a variable ends up with?

PLAY RECAP ************************** 06-ansible-cfg-and-precedence : ok=1 next=07-your-first-ad-hoc-command read=5m