Keywords: Ansible | SSH Authentication | Permission Denied | Host Configuration | Troubleshooting
Abstract: This article provides an in-depth analysis of the common SSH error "Permission denied (publickey,password)" in Ansible environments. Through practical case studies, it demonstrates proper configuration of Ansible inventory files, explains SSH authentication mechanisms in Ansible, and offers multiple troubleshooting approaches and best practices. The discussion extends to SSH key management, host verification, and other critical technical aspects to help readers comprehensively resolve Ansible connectivity issues.
Problem Background and Symptom Analysis
When using Ansible for automation operations, SSH connection errors represent one of the most frequent obstacles. Users report encountering SSH Error: Permission denied (publickey,password) when executing ansible all -m ping commands, despite successful SSH connections to target hosts via command line. This contradictory behavior indicates that the issue lies not in basic SSH connectivity but in Ansible-specific configuration or authentication mechanisms.
Core Problem Diagnosis
Analysis of detailed debug output reveals that Ansible employs specific authentication parameter combinations during SSH connections:
ssh -C -tt -vvv -o ControlMaster=auto -o ControlPersist=60s -o ControlPath="/Users/rajatg/.ansible/cp/ansible-ssh-%h-%p-%r" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 10.4.1.141
The critical parameter -o PasswordAuthentication=no explicitly disables password authentication, while -o PreferredAuthentications specifies the priority order of authentication methods. This demonstrates Ansible's default preference for public key authentication over password authentication.
Root Cause and Solution
The fundamental issue stems from improper configuration of the Ansible inventory file /etc/ansible/hosts. When the file contains only the IP address 10.4.1.141, Ansible cannot determine which user identity to employ for SSH connections, resulting in authentication failures.
The solution involves explicitly specifying the username in the host inventory:
# Incorrect configuration
10.4.1.141
# Correct configuration
rajat@10.4.1.141
This configuration approach explicitly informs Ansible to use the rajat user identity when connecting to target host 10.4.1.141, thereby resolving authentication issues caused by ambiguous user identity.
In-depth Analysis of SSH Authentication Mechanisms
Ansible relies on the SSH protocol for remote connections, with its authentication process following standard SSH authentication workflows. When using public key authentication, the system checks these critical files:
# Client private key location
~/.ssh/id_rsa
# Server public key authorization file
~/.ssh/authorized_keys
When configuring SSH key authentication, ensure:
- Private key file permissions are set to 600
- Public keys are correctly added to the target host's
authorized_keysfile - SSH daemon configuration permits public key authentication
Alternative Solutions and Best Practices
Beyond directly specifying usernames in the host inventory, consider these configuration approaches:
# Method 1: Using group configuration
[webservers]
10.4.1.141 ansible_user=rajat
# Method 2: Global user configuration
[all:vars]
ansible_user=rajat
For scenarios requiring password authentication, use the --ask-pass parameter:
ansible all -m ping -u rajat --ask-pass
Note that password authentication poses security risks in automation scripts, making SSH key authentication the recommended approach.
Troubleshooting and Debugging Techniques
When encountering SSH connection issues, employ this systematic troubleshooting approach:
- Verify Basic SSH Connectivity: First confirm command-line SSH functionality
- Enable Detailed Debugging: Use
-vvvvparameter for comprehensive SSH debug information - Check File Permissions: Verify proper permission settings for SSH-related files
- Validate Host Keys: Ensure target host keys are added to
known_hostsfile - Test Authentication Methods: Separately test availability of public key and password authentication
Configuration Examples and Code Implementation
Below is a complete Ansible configuration example demonstrating proper SSH connection setup:
# /etc/ansible/hosts file configuration
[development]
rajat@10.4.1.141
[production]
admin@192.168.1.100
operator@192.168.1.101
# SSH configuration example
# ~/.ssh/config
Host 10.4.1.141
User rajat
IdentityFile ~/.ssh/id_rsa
Port 22
In Python, simulate Ansible's SSH connection logic as follows:
import subprocess
import getpass
def test_ssh_connection(host, user=None):
"""Test SSH connection availability"""
if user:
target = f"{user}@{host}"
else:
target = host
try:
# Test basic connection
result = subprocess.run(
["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=5", target, "echo success"],
capture_output=True,
text=True
)
return result.returncode == 0
except Exception as e:
print(f"Connection test failed: {e}")
return False
# Usage example
if test_ssh_connection("10.4.1.141", "rajat"):
print("SSH connection test successful")
else:
print("SSH connection test failed")
Security Considerations and Best Practices
When deploying Ansible in production environments, consider these security best practices:
- Use SSH key pairs instead of passwords for authentication
- Regularly rotate SSH keys
- Limit SSH user privilege scope
- Enable SSH connection logging
- Use Ansible Vault to protect sensitive data
By adhering to these best practices, you can not only resolve current connectivity issues but also establish a more secure and reliable automation operations environment.