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}

Diagnose it: state, credentials, or drift?

Infrastructure failures in CI are usually about state access or credentials rather than the configuration itself. Confirm the runner can reach and lock state before reading the plan output.

Terminal
terraform init -backend=true -input=false
terraform providers
terraform plan -input=false -no-color -detailed-exitcode
#   exit 0 = no changes, 2 = changes present, 1 = error

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 Ansible "UNREACHABLE! failed to connect to the host via ssh"?
There are 2 common causes: transient network or host-not-yet-ready and dns, security group, or host-key issue. A freshly provisioned instance may not have SSH up yet, or a brief network blip drops the connection.
How do I fix Ansible "UNREACHABLE! failed to connect to the host via ssh"?
There are 2 fixes depending on which cause you have: add connection retries and wait for ssh and fix reachability and host-key handling. Work through them in order, since the first is the most common.
What does Ansible "UNREACHABLE! failed to connect to the host via ssh" actually mean?
A play aborts at the gathering-facts or first-task stage with UNREACHABLE!
How do I stop Ansible "UNREACHABLE! failed to connect to the host via ssh" happening again?
Use wait_for_connection before the first real task on freshly booted hosts. The prevention section lists 3 changes that keep it from recurring.
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

This is a transient network failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card