Failed to Connect via SSH in Ansible: Full Troubleshooting Guide
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
Fix Ansible SSH connection failures with step-by-step troubleshooting. Covers unreachable hosts, authentication failures, host key verification, connection.
SSH connection failures are the #1 blocker for Ansible beginners and a persistent headache for experienced users. This guide covers every SSH error you'll encounter, with diagnostic steps and fixes.
Diagnostic Flowchart
ansible host -m ping fails
├── "UNREACHABLE!" → Network/DNS/firewall issue (see Section 1)
├── "Permission denied" → Auth issue (see Section 2)
├── "Host key verification failed" → Known hosts (see Section 3)
├── Timeout → Network/firewall (see Section 4)
└── "Connection refused" → sshd not running (see Section 5)
See also: Ansible 'Failed to Connect via SSH localhost:22': Fix Guide
Step 0: Enable Debug Mode
# Always start with verbose output
ansible host -m ping -vvvv
# The -vvvv output shows:
# - SSH command being executed
# - Connection parameters
# - Authentication methods tried
# - Exact error from SSH
Section 1: UNREACHABLE — Host Not Found
Error
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname host: Name or service not known",
"unreachable": true
}
Diagnose
# Can you resolve the hostname?
nslookup hostname
dig hostname
# Can you reach the IP?
ping -c 3 hostname
# Can you reach SSH port?
nc -zv hostname 22
telnet hostname 22
Fix
# ansible.cfg or inventory — specify IP directly
[webservers]
web01 ansible_host=10.0.1.10
# Or fix DNS
# /etc/hosts
10.0.1.10 web01
See also: Ansible SSH with Passwords: Fix sshpass & Authentication (Guide)
Section 2: Permission Denied — Authentication Failure
Error
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: user@host: Permission denied (publickey,password)."
}
Diagnose
# Test SSH manually
ssh -v user@host
# Check which keys are being offered
ssh -v user@host 2>&1 | grep "Offering"
# Check if the key works
ssh -i ~/.ssh/my_key user@host
Fix: Wrong User
# inventory
[webservers]
web01 ansible_user=ubuntu # Not root, not your local user
# Or in ansible.cfg
[defaults]
remote_user = ubuntu
Fix: Wrong Key
# inventory
web01 ansible_ssh_private_key_file=~/.ssh/deploy_key
# Or in ansible.cfg
[defaults]
private_key_file = ~/.ssh/deploy_key
Fix: Key Permissions
# SSH requires strict key permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/config
Fix: Password Auth
# If using password (not recommended for production)
ansible host -m ping -k
# or
ansible host -m ping --ask-pass
# In inventory (avoid — password in plain text)
web01 ansible_password=secret # ❌ Don't do this
# Better: use sshpass for initial setup, then deploy keys
ansible-playbook setup-keys.yml -k
Section 3: Host Key Verification Failed
Error
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: Host key verification failed."
}
Fix: First Connection
# Accept the key manually first
ssh user@host
# "Are you sure you want to continue connecting?" → yes
# Or accept via ssh-keyscan
ssh-keyscan -H host >> ~/.ssh/known_hosts
Fix: Changed Host Key (Rebuild/New IP)
# Remove old key
ssh-keygen -R host
# Then connect again
ssh user@host
Fix: Disable Host Key Checking (Dev Only)
# ansible.cfg — NEVER in production
[defaults]
host_key_checking = False
# Or environment variable
export ANSIBLE_HOST_KEY_CHECKING=False
# Per-play
- hosts: dev_servers
gather_facts: false
vars:
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
See also: Ansible 'Connection failed' Error: Fix SSH & WinRM Issues (Guide)
Section 4: Connection Timeout
Error
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.1.10 port 22: Connection timed out"
}
Diagnose
# Is port 22 open?
nc -zv -w 5 host 22
# Check firewall on remote host (if accessible another way)
sudo iptables -L -n | grep 22
sudo ufw status
sudo firewall-cmd --list-ports
# Check security groups (cloud)
aws ec2 describe-security-groups --group-ids sg-xxx
Fix: Increase Timeout
# ansible.cfg
[defaults]
timeout = 30 # Default is 10 seconds
# For slow connections
[ssh_connection]
ssh_args = -o ConnectTimeout=30
Fix: Non-Standard Port
# inventory
web01 ansible_port=2222
# Or SSH config
# ~/.ssh/config
Host web01
HostName 10.0.1.10
Port 2222
Section 5: Connection Refused
Error
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.1.10 port 22: Connection refused"
}
Fix
# sshd not running — start it
sudo systemctl start sshd
sudo systemctl enable sshd
# sshd on wrong port — check config
grep "^Port" /etc/ssh/sshd_config
Section 6: Jump Host / Bastion
# ansible.cfg — SSH through a bastion
[ssh_connection]
ssh_args = -o ProxyJump=bastion_user@bastion.example.com
# Or per-host in inventory
web01 ansible_ssh_common_args='-o ProxyJump=ubuntu@bastion.example.com'
# SSH config approach (recommended)
# ~/.ssh/config
Host bastion
HostName bastion.example.com
User ubuntu
IdentityFile ~/.ssh/bastion_key
Host web-*
ProxyJump bastion
User deploy
IdentityFile ~/.ssh/deploy_key
Section 7: Privilege Escalation Failures
Error
host | FAILED! => {
"msg": "Missing sudo password"
}
Fix
# Provide sudo password
ansible-playbook site.yml -K
# or
ansible-playbook site.yml --ask-become-pass
# Or configure passwordless sudo on remote host
echo "deploy ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/deploy
# ansible.cfg
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
Section 8: SSH ControlPersist Issues
Error: Stale Control Socket
host | UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: ControlSocket ... already exists, disabling multiplexing"
}
Fix
# Remove stale control sockets
rm -rf ~/.ansible/cp/*
# Or change control path
# ansible.cfg
[ssh_connection]
control_path = %(directory)s/%%h-%%r-%%p
Complete ansible.cfg SSH Configuration
[defaults]
remote_user = deploy
private_key_file = ~/.ssh/deploy_key
host_key_checking = True
timeout = 30
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
control_path = %(directory)s/%%h-%%r-%%p
FAQ
Why does ansible -m ping fail but SSH works manually?
Common causes: different user (Ansible uses remote_user, not your shell user), different key (Ansible may use a different identity file), or SSH agent forwarding not passed. Compare ssh -v output with ansible -vvvv output.
How do I use SSH agent forwarding with Ansible?
Add ssh_args = -o ForwardAgent=yes to [ssh_connection] in ansible.cfg. Ensure your SSH agent has the key loaded (ssh-add -l). This is useful for Git operations on remote hosts.
Should I disable host key checking?
Only in ephemeral environments (CI/CD, disposable VMs) where hosts are created and destroyed frequently. In production, always verify host keys — disabling it enables MITM attacks.
How do I debug SSH connection issues?
Use ansible host -m ping -vvvv. The four-v output shows the exact SSH command, authentication methods tried, and the precise error. You can copy the SSH command and run it manually for further debugging.
Conclusion
SSH connection failures in Ansible always trace back to: network reachability, authentication (user/key/password), host key verification, or SSH daemon configuration. Start with -vvvv, test SSH manually, and work through the diagnostic flowchart above.
Related Articles
• Ansible SSH Password Authentication (sshpass) • Ansible Undefined Variable Error: Fixes • Ansible Check Mode / Dry Run Guide • Ansible Inventory GuideSee also
• Fix Ansible "UNREACHABLE" Error: Host Connection TroubleshootingCategory: troubleshooting