The Error
fatal: [remote-host]: FAILED! => {"changed": false, "cmd": "/usr/bin/git clone ...", "msg": "Host key verification failed.\r\nfatal: Could not read from remote repository."}
This pops up when the Ansible git module tries to clone via SSH (git@github.com:... or ssh://...) but the remote server's host key isn't in ~/.ssh/known_hosts. Specifically, it checks the user running the task on the target machine โ not your control node.
SSH blocks connections to unknown hosts. Ansible runs non-interactively, so there's no prompt to accept the key โ it just fails hard.
Why This Happens
Most people assume the problem is on the Ansible control node. It isn't. The known_hosts check happens on the remote host โ the machine being configured. That server has never SSH'd to your Git server before, so it has no record of the host key.
Four scenarios trigger this consistently:
- Fresh server provisioning โ first clone it's ever done
- Switching from HTTPS to SSH clone URLs
- Git server IP or key changed (GitHub rotated its RSA key in March 2023)
- Running the task as a different user like
deploy, who has noknown_hostsyet
Fix 1: Pre-populate known_hosts with ssh-keyscan (Recommended)
Drop a task before your git task to scan and register the host key:
- name: Add GitHub to known_hosts
ansible.builtin.known_hosts:
name: github.com
key: "{{ lookup('pipe', 'ssh-keyscan github.com') }}"
state: present
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:yourorg/yourrepo.git
dest: /opt/app
version: main
For GitLab or a private server, swap out github.com for your host:
- name: Add GitLab to known_hosts
ansible.builtin.known_hosts:
name: gitlab.example.com
key: "{{ lookup('pipe', 'ssh-keyscan gitlab.example.com') }}"
path: /home/deploy/.ssh/known_hosts
state: present
The path parameter is easy to overlook. Omit it and Ansible defaults to /etc/ssh/ssh_known_hosts. But if your git task runs as deploy, that user's SSH client checks /home/deploy/.ssh/known_hosts instead. Always set path explicitly to match the user running the clone.
Fix 2: Use accept_hostkey (Quick but Deprecated)
Older Ansible versions had an accept_hostkey parameter directly on the git module:
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:yourorg/yourrepo.git
dest: /opt/app
version: main
accept_hostkey: yes # deprecated in Ansible 2.12+
Ansible removed this in 2.12. If you're already seeing [DEPRECATION WARNING]: The 'accept_hostkey' argument is deprecated, migrate to Fix 1 now โ it'll stop working entirely in a future release.
Fix 3: Hard-code the Known Host Key
Running ssh-keyscan at task time makes a live network call. If you'd rather pin a specific key โ or if your environment blocks outbound SSH on port 22 โ grab the key once from your control node:
# On your control node:
ssh-keyscan github.com 2>/dev/null
Copy the output and embed it directly in your playbook:
- name: Add GitHub host key
ansible.builtin.known_hosts:
name: github.com
key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GkZH"
state: present
GitHub publishes its official fingerprints on their SSH key fingerprints docs page โ verify the key there before pinning it in production.
Fix 4: SSH Config on the Remote Host (Last Resort)
When you control the remote machine and need a quick unblock, you can disable strict host checking via SSH config:
- name: Disable StrictHostKeyChecking for git server
ansible.builtin.blockinfile:
path: /home/deploy/.ssh/config
create: yes
mode: '0600'
owner: deploy
block: |
Host github.com
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Restrict this to internal networks or isolated CI environments. StrictHostKeyChecking no silently accepts any host key โ including one from a MITM attacker. Don't use this in production.
Verify the Fix
SSH into the remote host and confirm the key landed:
# Check system-wide known_hosts
grep github.com /etc/ssh/ssh_known_hosts
# Or check user-level
grep github.com ~/.ssh/known_hosts
# Test the SSH connection directly
ssh -T git@github.com
# Expected: Hi username! You've successfully authenticated...
Re-run your playbook. The git task should clear without the host key error.
Tips
- known_hosts path mismatch: The path matters a lot. Tasks running as root need the key in
/root/.ssh/known_hostsor/etc/ssh/ssh_known_hosts. Tasks running asdeployneed it in/home/deploy/.ssh/known_hosts. Always specifypathexplicitly in theknown_hoststask โ don't let Ansible guess. - GitHub's 2023 RSA key rotation: GitHub replaced its RSA host key in March 2023. Hardcoded RSA keys from before that date will fail. Switch to the ED25519 key โ it hasn't changed and is more secure anyway.
- Multiple Git servers: Collect all your
known_hoststasks into a shared role or apre_tasksblock. Every host gets prepped before anygit cloneruns. - CI/CD pipelines: If GitHub Actions or GitLab CI runs your Ansible playbooks, the runner hits the same problem. Add an
ssh-keyscanstep to your pipeline setup before invoking Ansible. - Private servers on non-standard ports: Use
ssh-keyscan -p 2222 git.example.comand setname: "[git.example.com]:2222"in theknown_hoststask โ the bracket notation is required.

