The Error
fatal: [myserver]: UNREACHABLE! => {
"msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname myserver:
Name or service not known"
}
This means the control node's DNS can't resolve the hostname in your inventory to an IP address.
Quick Diagnosis
# Test from the Ansible control node (not your laptop)
ssh myserver
# ssh: Could not resolve hostname myserver: Name or service not known
# Try ping
ping -c 1 myserver
# ping: myserver: Name or service not known
# Try with FQDN
ping -c 1 myserver.example.com
# PING myserver.example.com (192.168.1.10) 56(84) bytes of data.
If FQDN works but short name doesn't, the issue is DNS search domain configuration.
5 Solutions
Solution 1: Use ansible_host with IP Addresses (Most Reliable)
# inventory.ini
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
db1 ansible_host=192.168.1.20
# inventory.yml
all:
children:
webservers:
hosts:
web1:
ansible_host: 192.168.1.10
web2:
ansible_host: 192.168.1.11
This decouples the inventory name from DNS — the most reliable approach.
Solution 2: Use FQDNs in Inventory
[webservers]
web1.example.com
web2.example.com
Solution 3: Add Entries to /etc/hosts
# On the Ansible control node
echo "192.168.1.10 web1 web1.example.com" | sudo tee -a /etc/hosts
echo "192.168.1.11 web2 web2.example.com" | sudo tee -a /etc/hosts
Or automate with Ansible (on a working host):
- name: Populate /etc/hosts
ansible.builtin.lineinfile:
path: /etc/hosts
line: "{{ hostvars[item].ansible_host }} {{ item }}"
state: present
loop: "{{ groups['all'] }}"
when: hostvars[item].ansible_host is defined
Solution 4: Fix DNS Configuration
# Check current DNS server
cat /etc/resolv.conf
# nameserver 8.8.8.8
# Test DNS resolution
nslookup myserver
dig myserver
host myserver
# Test with specific DNS server
dig @10.0.0.1 myserver.example.com
# Add search domain
echo "search example.com" | sudo tee -a /etc/resolv.conf
Solution 5: Fix DNS Search Domain
If short hostnames should resolve via a domain suffix:
# /etc/resolv.conf
nameserver 10.0.0.1
search example.com internal.company.com
Now myserver resolves as myserver.example.com.
Common Causes
| Cause | Symptom | Fix |
|---|---|---|
| Typo in inventory | One host fails | Check spelling |
| DNS server down | All hosts fail | Check /etc/resolv.conf |
| VPN not connected | Private hosts fail | Connect VPN first |
| Wrong inventory file | Wrong hosts targeted | ansible-playbook -i correct_inventory |
| Cloud instance rebuilt | IP changed | Update ansible_host |
| Split DNS (VPN) | Internal names fail | Check DNS over VPN |
Debugging Steps
1. Verify Which Inventory Ansible Uses
ansible-config dump | grep DEFAULT_HOST_LIST
# DEFAULT_HOST_LIST = ['/etc/ansible/hosts']
# Override with -i
ansible all -i my_inventory.ini --list-hosts
2. Test SSH Directly
# Test with the exact command Ansible would use
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 deploy@web1
3. Increase Verbosity
ansible web1 -m ping -i inventory -vvvv
# Shows the exact SSH command and DNS resolution attempt
4. Check for Stale DNS Cache
# Flush DNS cache
# systemd-resolved
sudo resolvectl flush-caches
# nscd
sudo nscd -i hosts
# dnsmasq
sudo systemctl restart dnsmasq
VPN and Network Issues
# Check if VPN is connected
ip route | grep tun
ip route | grep vpn
# Check if you can reach the network
ping -c 1 192.168.1.1 # Gateway
# Check firewall isn't blocking DNS
sudo ss -ulnp | grep :53
Ansible Configuration Options
# ansible.cfg
[defaults]
# Timeout for SSH connection
timeout = 30
# Retry failed hosts
retries = 3
[ssh_connection]
# SSH timeout
ssh_args = -o ConnectTimeout=30 -o ServerAliveInterval=15
Related Articles
- Ansible Best Practices Guide
- Ansible Configuration Settings
- Install Ansible on Ubuntu
- Test Host Availability: ping Module
- Ansible SSH Troubleshooting
Conclusion
"Could not resolve hostname" means DNS lookup failed on the control node. The most reliable fix is using ansible_host with IP addresses in your inventory. For DNS-based resolution, verify /etc/resolv.conf, check VPN connectivity for private networks, and test with dig/nslookup from the control node. Use ansible -vvvv to see the exact SSH command and pinpoint where resolution fails.