Skip to content
Latchkey

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.

ansible output
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.

playbook / ansible.cfg
- name: Wait for SSH
  ansible.builtin.wait_for_connection:
    timeout: 120
# ansible.cfg
[ssh_connection]
retries = 3

Fix reachability and host-key handling

  1. Confirm the host resolves and port 22 is open from the runner (nc -vz host 22).
  2. For ephemeral hosts in CI, set ANSIBLE_HOST_KEY_CHECKING=False or pre-seed known_hosts.
  3. Check the security group / firewall allows the runner’s egress IP.

How to prevent it

  • Use wait_for_connection before the first real task on freshly booted hosts.
  • Set sane SSH retries and timeout in ansible.cfg for flaky networks.
  • Manage known_hosts deliberately instead of disabling host-key checking in production.

Frequently asked questions

What causes ""UNREACHABLE!""?
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.
How do I fix "UNREACHABLE!"?
Wait for the port to come up before running the play, and let Ansible retry the transport.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card