Ansible "UNREACHABLE! Failed to connect to the host via ssh"
Ansible could not open an SSH connection to the managed host at all - before any task ran. The transport failed: a timeout, DNS failure, refused connection, or unverified host key.
What this error means
A play aborts at the gathering-facts or first-task stage with UNREACHABLE! and an SSH error. When the cause is a timed-out or reset connection, re-running often succeeds, which is the signature of a transient network problem rather than a config error.
fatal: [web01]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to
the host via ssh: ssh: connect to host 10.0.3.21 port 22: Connection timed out",
"unreachable": true}Common causes
Transient network or host-not-yet-ready
A freshly provisioned instance may not have SSH up yet, or a brief network blip drops the connection. Timeouts and resets here are usually transient and clear on retry.
DNS, security group, or host-key issue
The hostname does not resolve, a firewall/security group blocks port 22, or strict host-key checking rejects an unknown key - each presents as UNREACHABLE.
How to fix it
Add connection retries and wait for SSH
Wait for the port to come up before running the play, and let Ansible retry the transport.
- name: Wait for SSH
ansible.builtin.wait_for_connection:
timeout: 120
# ansible.cfg
[ssh_connection]
retries = 3Fix reachability and host-key handling
- Confirm the host resolves and port 22 is open from the runner (
nc -vz host 22). - For ephemeral hosts in CI, set
ANSIBLE_HOST_KEY_CHECKING=Falseor pre-seedknown_hosts. - Check the security group / firewall allows the runner’s egress IP.
How to prevent it
- Use
wait_for_connectionbefore the first real task on freshly booted hosts. - Set sane SSH
retriesandtimeoutinansible.cfgfor flaky networks. - Manage
known_hostsdeliberately instead of disabling host-key checking in production.