Skip to main content
RunBook Academy

AnsibleVI · Configuration and PrecedenceConfiguration and precedence

Which ansible.cfg is actually in effect

Intermediate⏱ ~16 minansible-core

What you'll learn

  • State the four configuration file locations in search order
  • Explain why settings in a lower-priority file have no effect at all rather than partial effect
  • Identify the config file in use from ansible --version before troubleshooting anything else
  • Predict how changing directory changes which configuration applies

Prerequisites

Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11

Not yet marked complete on this device.

An operator raises forks from 5 to 50 in /etc/ansible/ansible.cfg to speed up a fleet-wide run. The run takes exactly as long as before. They raise it to 100. No change. They check the file three times; the value is there.

The setting was never read. A project ansible.cfg existed in the directory they ran from, and that file was the only configuration Ansible loaded.

Four locations, in order

Ansible looks in these places and stops at the first one that exists:

#LocationNotes
1$ANSIBLE_CONFIGA file path, or a directory containing ansible.cfg
2./ansible.cfgThe current working directory only
3~/.ansible.cfgThe invoking user’s home directory
4/etc/ansible/ansible.cfgSystem-wide

One sentence carries most of the operational weight:

The first file found is used, and every other file is ignored completely. They do not merge.

Not “the higher-priority file wins where they conflict”. The others are not consulted at all. A setting that exists only in /etc/ansible/ansible.cfg has no effect from the moment a project ansible.cfg exists — even if the project file does not mention that setting.

Prove it. ~/.ansible.cfg sets both forks and timeout:

Read-only / Safehome config alone
$ ansible-config dump --only-changed
CONFIG_FILE() = /home/ops/.ansible.cfg
DEFAULT_FORKS(/home/ops/.ansible.cfg) = 3
DEFAULT_TIMEOUT(/home/ops/.ansible.cfg) = 60

Illustrative output

Now add a project ansible.cfg that sets forks and inventory, and says nothing about timeout:

Read-only / Safeproject config present
$ ansible-config dump --only-changed
CONFIG_FILE() = /srv/estate/ansible.cfg
DEFAULT_FORKS(/srv/estate/ansible.cfg) = 30
DEFAULT_HOST_LIST(/srv/estate/ansible.cfg) = ['/srv/estate/inventory']

Illustrative output

DEFAULT_TIMEOUT is gone. It has not been overridden by a different value — it has reverted to the built-in default of 10, because the file that set it was never opened. Both captures are from ansible-core 2.21.3; the paths have been shortened for the page.

The one command that answers the question

Before diagnosing anything about Ansible behaviour, establish which configuration is in force. ansible --version reports it on the second line:

Read-only / Safethe first troubleshooting step
$ ansible --version
ansible [core 2.21.3]
config file = /srv/estate/ansible.cfg
configured module search path = ['/home/ops/.ansible/plugins/modules']
ansible python module location = /home/ops/.venvs/estate/lib/python3.12/site-packages/ansible
ansible collection location = /home/ops/.ansible/collections:/usr/share/ansible/collections
executable location = /home/ops/.venvs/estate/bin/ansible
python version = 3.12.7
jinja version = 3.1.4
pyyaml version = 6.0.3 (with libyaml v0.2.5)

Illustrative output

When no file is found anywhere, the line is explicit, and this is a real state rather than an error:

ansible [core 2.21.3]
  config file = None

Every setting is then at its built-in default: forks 5, timeout 10, host_key_checking true, inventory /etc/ansible/hosts.

The working directory is part of your configuration

Location 2 is ./ansible.cfg, and . means the current working directory. There is no search upward through parent directories.

This is worth stating plainly because it contradicts the mental model most people bring from Git, .editorconfig, tox.ini and every other project-root file they have used:

/srv/estate/
    ansible.cfg          <- the project configuration
    site.yml
    inventory/
    playbooks/
        patching.yml

Run from /srv/estate, the project config is found. Run from /srv/estate/playbooks, it is not — Ansible finds nothing in the current directory and falls through to ~/.ansible.cfg, then to /etc/ansible/ansible.cfg, then to nothing.

Confirmed on 2.21.3: invoking from a subdirectory of a project that has an ansible.cfg at its root reported config file pointing at the home directory file instead.

ANSIBLE_CONFIG accepts a directory

A small convenience with a real use. ANSIBLE_CONFIG may name either a file or a directory; given a directory, Ansible looks for ansible.cfg inside it. Verified on 2.21.3.

ANSIBLE_CONFIG=/srv/estate ansible --version

That resolves to /srv/estate/ansible.cfg. It makes wrapper scripts and CI definitions a little less brittle — they point at the project root, which is a stable fact, rather than at a filename, which is a convention.

Knowledge check

Knowledge check · 4 questions

  1. Q1. A project ansible.cfg sets forks = 30 and says nothing about timeout. The user home file ~/.ansible.cfg sets timeout = 60. Running from the project directory, what is the effective timeout?

  2. Q2. Running ansible-playbook from a subdirectory of a project whose ansible.cfg is at the project root still loads that project configuration.

  3. Q3. Which of these are true of ANSIBLE_CONFIG on ansible-core 2.21.3? Select all that apply.

  4. Q4. An engineer raises forks in /etc/ansible/ansible.cfg and the fleet-wide run takes exactly as long as before. What is the first command to run?

Passing score: 75%. Answers are checked in this browser.