Introduction
The ansible.cfg file is Ansible's primary configuration file, controlling everything from SSH connection behavior to module paths and output formatting. One of the most impactful recent changes affecting Ansible users is the deprecation of the SCP protocol in OpenSSH 9.0 (shipped with RHEL 9, Ubuntu 22.04+, and Fedora 36+). If your playbooks suddenly fail with file transfer errors after an OS upgrade, this is likely the cause.
This guide covers the ansible.cfg SSH settings you need to understand, how to handle the SCP deprecation, and best practices for optimal SSH performance.
ansible.cfg File Locations
Ansible searches for configuration in this order (first found wins):
ANSIBLE_CONFIGenvironment variable./ansible.cfg(current directory)~/.ansible.cfg(home directory)/etc/ansible/ansible.cfg(global)
Best practice: Keep ansible.cfg in your project directory alongside your playbooks and commit it to version control.
# Check which config file Ansible is using
ansible --version | grep "config file"
The SCP Deprecation in OpenSSH 9.0
What Changed
Starting with OpenSSH 9.0 (RHEL 9, Ubuntu 22.04+):
- The
scpcommand now uses SFTP protocol internally by default - The legacy SCP protocol can be restored with the
-Oflag - Future OpenSSH releases will remove SCP protocol support entirely
Impact on Ansible
Ansible uses file transfer for modules, facts, and the copy/fetch/template modules. If your ansible.cfg explicitly set transfer_method = scp, file transfers may fail on systems running OpenSSH 9.0+:
fatal: [host]: FAILED! => {"msg": "scp transfer failed"}
The Fix
Option 1: Use SFTP (Recommended)
Remove any explicit transfer_method setting or set it to smart:
[ssh_connection]
transfer_method = smart
The smart method (default) tries SFTP first, then falls back to SCP. This works on both old and new OpenSSH versions.
Option 2: Keep SCP with -O flag (Temporary)
If you must use SCP (e.g., for compatibility with very old systems):
[ssh_connection]
transfer_method = scp
scp_extra_args = -O
The -O flag forces the legacy SCP protocol. However, this is a temporary solution — the -O flag may be removed in future OpenSSH releases.
Option 3: Force SFTP only
[ssh_connection]
transfer_method = sftp
Complete ansible.cfg Reference for SSH
[defaults]
# Number of parallel processes
forks = 20
# Default connection type
transport = ssh
# Disable host key checking (use with caution)
host_key_checking = False
# Timeout for SSH connection
timeout = 30
[ssh_connection]
# SSH arguments for ControlMaster multiplexing
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
# File transfer method: smart (default), sftp, scp
transfer_method = smart
# Enable pipelining (significant performance improvement)
pipelining = True
# Extra arguments for SCP (if using SCP transfer)
scp_extra_args = -O
# Extra arguments for SFTP
sftp_extra_args =
# Extra arguments for SSH
ssh_extra_args =
# ControlPath for SSH multiplexing
control_path_dir = /tmp/.ansible/cp
control_path = %(directory)s/%%h-%%r-%%p
# Retries for SSH connections
retries = 3
Key Settings Explained
ssh_args and ControlMaster
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
- ControlMaster=auto: Enables SSH connection multiplexing — the first SSH connection to a host creates a control socket, and subsequent connections reuse it
- ControlPersist=60s: Keeps the control socket alive for 60 seconds after the last connection closes
This dramatically reduces SSH handshake overhead when running multiple tasks against the same host.
pipelining
pipelining = True
When enabled, Ansible sends the module code through the SSH pipe instead of copying it as a file. This eliminates one SFTP/SCP transfer per task, significantly improving performance.
Requirement: The remote user must not have requiretty set in /etc/sudoers. Check with:
grep requiretty /etc/sudoers
If found, comment it out or add an exception:
Defaults:ansible_user !requiretty
transfer_method
| Value | Behavior |
|---|---|
smart | Try SFTP first, fall back to SCP (default, recommended) |
sftp | Use SFTP only |
scp | Use SCP only (requires -O on OpenSSH 9.0+) |
forks
forks = 20
Controls how many hosts Ansible manages in parallel. Default is 5, which is conservative. For large inventories, increase to 20-50 depending on your control node's resources.
Performance-Optimized ansible.cfg
A production-ready configuration for maximum SSH performance:
[defaults]
forks = 30
host_key_checking = False
timeout = 30
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 3600
stdout_callback = yaml
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600s -o PreferredAuthentications=publickey
transfer_method = smart
pipelining = True
control_path_dir = /tmp/.ansible/cp
retries = 3
Key improvements:
- ControlPersist=600s: 10-minute persistence for long playbook runs
- PreferredAuthentications=publickey: Skip password auth attempts
- pipelining=True: Major speed improvement
- fact_caching: Cache facts for 1 hour to skip repeated gathering
Environment-Specific Configurations
Development
[defaults]
forks = 5
host_key_checking = False
deprecation_warnings = True
stdout_callback = debug
Production
[defaults]
forks = 30
host_key_checking = True
log_path = /var/log/ansible/ansible.log
no_log = True
stdout_callback = yaml
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600s -o StrictHostKeyChecking=yes
pipelining = True
retries = 3
Network Devices
[defaults]
forks = 10
timeout = 60
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o KexAlgorithms=+diffie-hellman-group14-sha1
pipelining = False # Often required for network devices
CVE-2020-15778: SCP Vulnerability
The SCP protocol has known security vulnerabilities. CVE-2020-15778 allows remote code execution through crafted file names during SCP transfers. This is one of the primary reasons OpenSSH deprecated SCP:
# Vulnerable: SCP protocol
transfer_method = scp
# Secure: SFTP protocol
transfer_method = sftp
Recommendation: Always use SFTP unless you have a specific compatibility requirement.
Troubleshooting SSH Issues
Connection Timeout
[defaults]
timeout = 60 # Increase from default 10
[ssh_connection]
ssh_args = -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=3
SSH Key Issues
# Test SSH connection manually
ssh -vvv user@host
# Specify key in ansible.cfg
[defaults]
private_key_file = ~/.ssh/ansible_key
ControlMaster Socket Errors
If you see stale socket errors:
# Clean up stale control sockets
rm -rf /tmp/.ansible/cp/*
Related Articles
- Ansible Connection Failed Errors
- Ansible Best Practices Guide
- Ansible Vault Guide
- 10 Ways to Speed Up Your Ansible Playbooks
- Securing Ansible: Managing Sudo Passwords
- Privilege Escalation Errors
- How to Install Ansible
Conclusion
The ansible.cfg file is the control center for Ansible's behavior, and getting SSH settings right is critical for both performance and security. With the SCP deprecation in OpenSSH 9.0+, the key takeaway is: use transfer_method = smart (or sftp), enable pipelining, and configure ControlMaster for connection multiplexing. These three settings alone can cut playbook execution time by 50% or more while keeping your file transfers secure.