Where Ansible Looks for ansible.cfg
Ansible searches the following locations in order and uses the first match it finds (it does not merge them):
$ANSIBLE_CONFIG— environment variable pointing to a specific file./ansible.cfg— a file in your current working directory (the most common in projects)~/.ansible.cfg— your user's home directory/etc/ansible/ansible.cfg— system-wide default (installed with Ansible)
💡 Tip: Project-level
./ansible.cfg is what you want 99% of the time. Drop one at the root of every Ansible repo and check it into git so the whole team gets the same behaviour. A Production-Ready ansible.cfg
INI — ansible.cfg
[defaults]
# inventory location
inventory = ./inventories/production/hosts.ini
# performance — number of parallel SSH connections
forks = 25
# host key checking — disable for dev clusters with throwaway VMs
# leave on (true) for production!
host_key_checking = False
# faster lookups: cache facts between runs (1 hour TTL)
gathering = smart
fact_caching = jsonfile
fact_caching_connection = ./.fact_cache
fact_caching_timeout = 3600
# nicer output
stdout_callback = yaml
callbacks_enabled = profile_tasks, timer
# default user (overridden by inventory or playbook)
remote_user = deploy
# where to look for roles and collections
roles_path = ./roles:./shared-roles
collections_paths = ./collections:~/.ansible/collections
# log everything
log_path = ./ansible.log
# skip the cow
nocows = True
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
# pipelining halves the number of SSH operations per task — big speedup
pipelining = True
# multiplex SSH connections so we don't reconnect for every task
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o PreferredAuthentications=publickey
# bigger transfer buffer
control_path_dir = ~/.ansible/cp
The Settings That Matter Most
| Setting | Default | What changes when you raise/lower it |
|---|---|---|
forks | 5 | Parallel hosts per task. 25–50 is fine for most LANs. |
host_key_checking | True | True = secure, False = no SSH "yes/no?" prompt for new hosts |
gathering | implicit | smart = use cache if fresh, otherwise re-gather |
pipelining | False | True almost halves run time — turn it on |
stdout_callback | default | yaml shows multi-line output cleanly; debug for diff'ing |
retry_files_enabled | True (legacy) | Set False so failed runs don't drop *.retry files |
Pipelining — The Biggest Single Speed-Up
Without pipelining, Ansible does three SSH operations per task: SFTP the module
file, SSH to chmod it, then SSH again to execute. With pipelining, the module is
piped directly into the SSH session and executed inline — one SSH op per task.
INI — enable pipelining
[ssh_connection]
pipelining = True
⚠ Warning: Pipelining requires
requiretty to be off in /etc/sudoers on the managed nodes. OEL 8 ships with this already disabled, so it just works. Older RHEL 6 / CentOS 6 boxes may need the line Defaults !requiretty added. Inspect Resolved Configuration
Ansible can show you which config file it picked up and what every setting resolves to:
BASH — show resolved config
# show which file Ansible is reading
ansible --version | grep "config file"
# dump every setting and where it came from
ansible-config dump --only-changed
# show the full list of every option (with current value & default)
ansible-config list | head -30
✅ Tip: Run
ansible-config dump --only-changed at the start of any new project — it tells you exactly what your ansible.cfg overrides vs the defaults.