Ansible Configuration
Introduction
Ansible's behavior can be extensively customized through configuration files, environment variables, and command-line options. Understanding the configuration system is essential for optimizing performance, managing authentication, controlling output, and adapting Ansible to your specific environment.
Configuration Precedence (Highest to Lowest):
- Command-line options:
ansible-playbook -f 50 - Environment variables:
ANSIBLE_FORKS=50 - ansible.cfg (current directory):
./ansible.cfg - User configuration:
~/.ansible.cfg - System configuration:
/etc/ansible/ansible.cfg
Finding Your Configuration
View Current Configuration
# Show which config file is being used
ansible --version
# Output shows:
# ansible [core 2.14.0]
# config file = /etc/ansible/ansible.cfg
# configured module search path = ['/home/user/.ansible/plugins/modules']
# View all configuration settings
ansible-config dump
# View only changed settings
ansible-config dump --only-changed
# View configuration for specific setting
ansible-config dump | grep -i forks
# List all available settings
ansible-config list
Configuration File Locations
# Check which config file Ansible will use
export ANSIBLE_CONFIG=/path/to/ansible.cfg # Highest priority
./ansible.cfg # Project-specific
~/.ansible.cfg # User-specific
/etc/ansible/ansible.cfg # System-wide (default)
# Verify active configuration
ansible-config view
# Check if a specific config file is valid
ansible-config view -c /path/to/ansible.cfg
Complete ansible.cfg Reference
[defaults] Section
The [defaults] section contains the most commonly used settings:
[defaults]
# Inventory settings
inventory = ./inventory
# inventory = /etc/ansible/hosts
# Can be file, directory, or comma-separated list
# Roles and collections paths
roles_path = ./roles:/usr/share/ansible/roles
collections_path = ./collections:/usr/share/ansible/collections
# Connection settings
remote_user = ansible
# Default user for SSH connections
timeout = 10
# SSH connection timeout in seconds
host_key_checking = False
# Disable SSH host key checking (useful for dynamic environments)
# Security risk: set to True in production
# Performance tuning
forks = 5
# Number of parallel processes (increase for larger inventories)
# Recommended: CPU cores * 2 to 4
gathering = smart
# Fact gathering: implicit (always), explicit (never unless requested), smart (cache)
fact_caching = jsonfile
# Cache facts to speed up playbook runs: memory, jsonfile, redis, yaml
fact_caching_connection = /tmp/ansible_facts
# Where to store cached facts
fact_caching_timeout = 86400
# Fact cache expiration in seconds (86400 = 24 hours)
# Output and logging
stdout_callback = yaml
# Output format: default, yaml, json, minimal, debug
bin_ansible_callbacks = True
# Use callbacks from collections
log_path = /var/log/ansible.log
# Path to log file (must be writable by user)
display_skipped_hosts = False
# Show tasks that were skipped
display_ok_hosts = True
# Show successful tasks
# Error handling
retry_files_enabled = False
# Create .retry files for failed hosts
retry_files_save_path = ./
# Where to save .retry files
any_errors_fatal = False
# Stop entire playbook on any error
# Module and plugin settings
module_name = command
# Default module for ad-hoc commands
library = /usr/share/ansible/modules
# Additional module search paths
action_plugins = /usr/share/ansible/plugins/action
callback_plugins = /usr/share/ansible/plugins/callback
connection_plugins = /usr/share/ansible/plugins/connection
filter_plugins = /usr/share/ansible/plugins/filter
lookup_plugins = /usr/share/ansible/plugins/lookup
test_plugins = /usr/share/ansible/plugins/test
# Python interpreter
interpreter_python = auto_silent
# How to find Python: auto, auto_legacy, auto_silent, /usr/bin/python3
# Warnings and deprecations
deprecation_warnings = True
command_warnings = True
system_warnings = True
# Vault
vault_password_file = ~/.vault_pass
# Path to file containing vault password
vault_identity_list = dev@~/.vault_pass_dev, prod@~/.vault_pass_prod
# Multiple vault passwords with labels
# Miscellaneous
nocows = 1
# Disable cowsay output
nocolor = 0
# Disable colored output (1 = disable, 0 = enable)
force_color = 0
# Force colored output even when not in TTY
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
# Header for templates to show they're managed by Ansible
jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n
# Additional Jinja2 extensions
# Task execution
poll_interval = 15
# How often to poll for async task status
internal_poll_interval = 0.001
# Internal task polling interval
# Variable handling
hash_behaviour = replace
# How to merge hashes: replace or merge (replace is recommended)
# Inventory plugins
enable_plugins = host_list, script, auto, yaml, ini, toml
# Which inventory plugins to enable
[privilege_escalation] Section
Settings for privilege escalation (sudo, su, etc.):
[privilege_escalation]
become = True
# Enable privilege escalation by default
become_method = sudo
# Method: sudo, su, pbrun, pfexec, doas, dzdo, ksu, runas, machinectl
become_user = root
# User to become (usually root)
become_ask_pass = False
# Prompt for privilege escalation password
become_flags = -H -S -n
# Additional flags for become command
# Method-specific settings
[sudo_become_plugin]
flags = -H -S -n
# Sudo-specific flags
[pbrun_become_plugin]
flags = -l
# Pbrun-specific flags
[ssh_connection] Section
SSH connection optimization:
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
# SSH arguments for connection multiplexing
# -C: compression
# ControlMaster: reuse connections
# ControlPersist: keep connections alive
control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r
# Path for SSH control socket
# %%h = hostname, %%p = port, %%r = remote user
pipelining = True
# Enable SSH pipelining (huge performance boost)
# Requires requiretty disabled in /etc/sudoers
scp_if_ssh = smart
# When to use SCP vs SFTP: smart, True, False
transfer_method = smart
# How to transfer files: smart, sftp, scp, piped
retries = 3
# Number of SSH connection retries
timeout = 10
# SSH connection timeout in seconds
ssh_executable = /usr/bin/ssh
# Path to SSH binary
sftp_batch_mode = True
# Disable confirmation prompts in SFTP
[persistent_connection] Section
Settings for persistent network connections:
[persistent_connection]
connect_timeout = 30
# Timeout for establishing connection
connect_retry_timeout = 15
# Timeout before retrying connection
command_timeout = 30
# Timeout for commands on persistent connection
[colors] Section
Customize output colors:
[colors]
highlight = white
verbose = blue
warn = bright purple
error = red
debug = dark gray
deprecate = purple
skip = cyan
unreachable = red
ok = green
changed = yellow
diff_add = green
diff_remove = red
diff_lines = cyan
[selinux] Section
SELinux-specific settings:
[selinux]
special_context_filesystems = fuse, nfs, vboxsf, ramfs, 9p, vfat
# Filesystems that require special SELinux handling
libvirt_lxc_noseclabel = yes
# Don't set SELinux labels on libvirt LXC containers
Environment Variables
Common Environment Variables
# Configuration file location
export ANSIBLE_CONFIG=/path/to/ansible.cfg
# Connection settings
export ANSIBLE_HOST_KEY_CHECKING=False
export ANSIBLE_REMOTE_USER=ansible
export ANSIBLE_REMOTE_PORT=22
export ANSIBLE_TIMEOUT=10
# Performance
export ANSIBLE_FORKS=50
export ANSIBLE_GATHERING=smart
export ANSIBLE_CACHE_PLUGIN=jsonfile
export ANSIBLE_CACHE_PLUGIN_CONNECTION=/tmp/facts_cache
export ANSIBLE_CACHE_PLUGIN_TIMEOUT=86400
# Pipelining (requires requiretty disabled)
export ANSIBLE_PIPELINING=True
export ANSIBLE_SSH_PIPELINING=True
# Inventory
export ANSIBLE_INVENTORY=/path/to/inventory
export ANSIBLE_INVENTORY_ENABLED=host_list,script,auto,yaml,ini
# Output and logging
export ANSIBLE_STDOUT_CALLBACK=yaml
export ANSIBLE_LOG_PATH=/var/log/ansible.log
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
export ANSIBLE_DISPLAY_OK_HOSTS=True
export ANSIBLE_CALLBACK_WHITELIST=timer,profile_tasks
# Privilege escalation
export ANSIBLE_BECOME=True
export ANSIBLE_BECOME_METHOD=sudo
export ANSIBLE_BECOME_USER=root
export ANSIBLE_BECOME_ASK_PASS=False
# Python interpreter
export ANSIBLE_PYTHON_INTERPRETER=/usr/bin/python3
# Vault
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
export ANSIBLE_VAULT_IDENTITY_LIST=dev@~/.vault_dev,prod@~/.vault_prod
# Roles and collections
export ANSIBLE_ROLES_PATH=./roles:/usr/share/ansible/roles
export ANSIBLE_COLLECTIONS_PATH=./collections:~/.ansible/collections
# Module paths
export ANSIBLE_LIBRARY=/usr/share/ansible/modules
export ANSIBLE_MODULE_UTILS=/usr/share/ansible/module_utils
# Plugin paths
export ANSIBLE_ACTION_PLUGINS=/path/to/action_plugins
export ANSIBLE_CALLBACK_PLUGINS=/path/to/callback_plugins
export ANSIBLE_CONNECTION_PLUGINS=/path/to/connection_plugins
export ANSIBLE_FILTER_PLUGINS=/path/to/filter_plugins
export ANSIBLE_LOOKUP_PLUGINS=/path/to/lookup_plugins
export ANSIBLE_TEST_PLUGINS=/path/to/test_plugins
# Error handling
export ANSIBLE_RETRY_FILES_ENABLED=False
export ANSIBLE_ANY_ERRORS_FATAL=False
# Debugging
export ANSIBLE_DEBUG=False
export ANSIBLE_VERBOSE_TO_STDERR=False
# Miscellaneous
export ANSIBLE_NOCOWS=1
export ANSIBLE_NOCOLOR=0
export ANSIBLE_FORCE_COLOR=0
export ANSIBLE_DEPRECATION_WARNINGS=True
export ANSIBLE_COMMAND_WARNINGS=True
Setting Environment Variables Temporarily
# For a single command
ANSIBLE_FORKS=50 ansible-playbook playbook.yml
# For current shell session
export ANSIBLE_FORKS=50
ansible-playbook playbook.yml
# In playbook
- name: Set environment for tasks
hosts: all
environment:
ANSIBLE_DEBUG: True
tasks:
- name: Debug task
debug:
msg: "Debugging enabled"
Configuration Examples
Development Environment
[defaults]
inventory = ./inventory/dev
roles_path = ./roles
collections_path = ./collections
# Speed up development with these settings
host_key_checking = False
gathering = explicit # Don't gather facts unless needed
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_dev
retry_files_enabled = False
# Verbose output for debugging
stdout_callback = yaml
display_skipped_hosts = False
callbacks_enabled = timer, profile_tasks
# Performance
forks = 10
timeout = 10
# Python
interpreter_python = auto_silent
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
Production Environment
[defaults]
inventory = /etc/ansible/inventory/production
roles_path = /etc/ansible/roles:/usr/share/ansible/roles
collections_path = /etc/ansible/collections
# Security
host_key_checking = True
private_key_file = /etc/ansible/.ssh/ansible_rsa
# Performance optimization
forks = 50
gathering = smart
fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_timeout = 3600
# Logging
log_path = /var/log/ansible/ansible.log
display_skipped_hosts = False
display_ok_hosts = False
# Error handling
retry_files_enabled = True
retry_files_save_path = /var/log/ansible/retries/
any_errors_fatal = False
# Callbacks for monitoring
callbacks_enabled = timer, profile_tasks, profile_roles, log_plays
# Output
stdout_callback = default
bin_ansible_callbacks = True
# Python
interpreter_python = /usr/bin/python3
# Vault
vault_identity_list = prod@/etc/ansible/.vault_pass_prod
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=3600s
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
scp_if_ssh = smart
transfer_method = smart
retries = 5
timeout = 30
High-Performance Configuration
[defaults]
# Maximize parallelism
forks = 100
strategy = free # Don't wait for all hosts between tasks
# Optimize fact gathering
gathering = smart
fact_caching = redis
fact_caching_connection = localhost:6379:0
fact_caching_timeout = 86400
# Minimal output
stdout_callback = minimal
display_skipped_hosts = False
display_ok_hosts = False
# No retry files
retry_files_enabled = False
# Performance callbacks
callbacks_enabled = profile_tasks, profile_roles
[ssh_connection]
# Enable pipelining (biggest performance boost)
pipelining = True
# Optimize SSH multiplexing
ssh_args = -o ControlMaster=auto -o ControlPersist=3600s -o PreferredAuthentications=publickey
control_path = %(directory)s/ssh-%%C
# Use SFTP for file transfers
transfer_method = sftp
sftp_batch_mode = True
# Connection pooling
retries = 3
timeout = 30
Security-Focused Configuration
[defaults]
# Strict security
host_key_checking = True
private_key_file = /secure/path/ansible_rsa
# Logging and audit trail
log_path = /var/log/ansible/ansible.log
callbacks_enabled = log_plays, syslog
# No caching of sensitive data
fact_caching = memory
gathering = explicit
# Vault for all secrets
vault_identity_list = main@/secure/path/.vault_pass
# No retry files (may contain sensitive data)
retry_files_enabled = False
# Strict variable handling
hash_behaviour = replace
inject_facts_as_vars = False
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = True # Always prompt for password
[ssh_connection]
# Secure SSH settings
ssh_args = -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/etc/ansible/known_hosts
pipelining = False # Disabled if requiretty is enforced
timeout = 10
retries = 1
Per-Project Configuration
Project Directory Structure
project/
├── ansible.cfg # Project-specific configuration
├── inventory/
│ ├── production
│ ├── staging
│ └── development
├── group_vars/
├── host_vars/
├── roles/
├── collections/
└── playbooks/
# ansible.cfg in project root
[defaults]
inventory = ./inventory
roles_path = ./roles
collections_path = ./collections
retry_files_enabled = False
host_key_checking = False
Environment-Specific Configs
# Run with specific config file
ansible-playbook -c ./configs/ansible-dev.cfg playbook.yml
ANSIBLE_CONFIG=./configs/ansible-prod.cfg ansible-playbook playbook.yml
# configs/ansible-dev.cfg
[defaults]
inventory = ./inventory/dev
forks = 10
gathering = explicit
# configs/ansible-prod.cfg
[defaults]
inventory = ./inventory/prod
forks = 50
gathering = smart
Debugging Configuration Issues
Troubleshooting Commands
# Show active configuration
ansible-config dump --only-changed
# Test configuration
ansible --version
ansible-config view
# Verify inventory configuration
ansible-inventory --list
ansible-inventory --graph
# Test connection with configuration
ansible all -m ping -vvv
# Check specific setting
ansible-config dump | grep forks
# Validate configuration file
ansible-config view -c ./ansible.cfg
# Show all settings and their origins
ansible-config dump -v
# List all configuration options
ansible-config list | less
Common Configuration Problems
Common Issues:
- Wrong config file loaded: Check with
ansible --version - Pipelining not working: Disable requiretty in /etc/sudoers
- SSH key issues: Verify
private_key_filepath and permissions - Slow performance: Increase forks, enable pipelining, use fact caching
- Permission denied: Check become settings and SSH user
- Module not found: Verify library and plugin paths
- Fact caching not working: Check cache plugin connection and timeout
Best Practices
Configuration Best Practices:
- Use project-local configs: Keep ansible.cfg in project root
- Version control: Commit ansible.cfg to git (except sensitive data)
- Document settings: Add comments explaining non-obvious settings
- Environment-specific: Use different configs for dev/staging/prod
- Test changes: Always test configuration changes in dev first
- Security first: Enable host_key_checking in production
- Optimize gradually: Start with defaults, tune based on needs
- Monitor performance: Use timer and profile_tasks callbacks
- Keep it simple: Only change settings you understand
- Regular reviews: Periodically review and update configuration
Next Steps
- Learn about Logging and Monitoring for audit trails
- Explore Security Best Practices for hardening
- Master Troubleshooting configuration issues
- Study Advanced Topics for complex scenarios
- Practice in the Playground with different configurations