Fix "Host key verification failed." in SSH, Git and scripts
Connect once in a normal terminal, as the same user that runs the failing command, check the fingerprint and answer yes. The key is then stored in ~/.ssh/known_hosts and later non-interactive runs succeed.
# replace with your server or Git host
ssh -T [email protected]
ssh [email protected]
# then re-run the command that failed
The message usually appears on its own, or at the end of a Git or rsync error:
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
What the error means
Every SSH server has a host key. On the first connection ssh shows its fingerprint and asks whether to trust it; your answer is saved in ~/.ssh/known_hosts. On later connections ssh compares the server's key with the saved one. "Host key verification failed." means that check did not pass and ssh stopped before authentication, so your login key was never even tried.
Look at what is printed above the error, because it decides which fix you need:
| Printed before the error | Meaning | Go to |
|---|---|---|
Nothing, or The authenticity of host ... can't be established | The key is unknown and ssh could not ask you (no terminal, batch mode) | Causes 1 to 3 below |
No ED25519 host key is known for ... and you have requested strict checking | Key unknown and StrictHostKeyChecking yes is set | Cause 4 below |
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! | A saved key exists but does not match | REMOTE HOST IDENTIFICATION HAS CHANGED |
This page covers the first two rows: the server key is simply not known to the account and context that runs ssh.
Cause 1: a script, Git or CI job runs ssh without a terminal
This is the most common case. The "yes/no" question needs a terminal. Git hooks, IDEs, cron jobs, systemd services, CI runners and ssh -o BatchMode=yes have none, so ssh cannot ask and fails immediately. It works in your terminal only because you answered the question there at some point.
Fix it by adding the key to known_hosts once, after checking it. ssh-keyscan fetches the key, and ssh-keygen -lf shows its fingerprint so you can compare it with the value the server owner or Git host publishes:
ssh-keyscan -t ed25519 github.com > /tmp/gh.key
ssh-keygen -lf /tmp/gh.key
# compare the SHA256 fingerprint with the one the host publishes, then:
mkdir -p -m 700 ~/.ssh
cat /tmp/gh.key >> ~/.ssh/known_hosts
GitHub, GitLab, Bitbucket and Codeberg publish their host key fingerprints in their documentation. For your own servers, read the fingerprint on the server console:
# run on the server
for f in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$f"; done
StrictHostKeyChecking no or UserKnownHostsFile /dev/null in a global config makes ssh trust any server, including an attacker in the middle. A blind ssh-keyscan >> known_hosts without checking the fingerprint is only slightly better (trust on first use).
Cause 2: a different user, so a different known_hosts
known_hosts is per user. You accepted the key as alice, but the failing command runs as someone else:
sudo git pullorsudo sshruns as root and reads/root/.ssh/known_hosts.- A web server deploy hook runs as
www-data(Debian/Ubuntu) orapache/nginx(Fedora). - A systemd service or cron entry runs under a service account, often with a different
HOME.
Check which user and file are used by running the same command with -v:
sudo -u deploy ssh -v [email protected] 2>&1 | grep -i known_hosts
Example output:
debug1: load_hostkeys: fopen /home/deploy/.ssh/known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
Either accept the key as that user (sudo -u deploy ssh -T [email protected]), or, for keys every account on the machine should trust, add the verified line to the system-wide file /etc/ssh/ssh_known_hosts. Avoid running Git with sudo at all; if you do it to fix ownership errors, see detected dubious ownership instead.
Cause 3: Docker builds and fresh containers
A new container or image has an empty home directory, so git clone git@... inside a Dockerfile or a CI container always fails the first time. Ship a known, checked key with the build instead of scanning at build time:
# known_hosts file you verified once and keep in the repository
COPY known_hosts /root/.ssh/known_hosts
RUN chmod 700 /root/.ssh && chmod 644 /root/.ssh/known_hosts
Most CI systems (GitHub Actions, GitLab CI, Jenkins) let you store the known_hosts content as a variable or secret and write it to ~/.ssh/known_hosts in the job. That keeps the protection and survives runner rebuilds. For Docker itself see Docker on Linux.
Cause 4: StrictHostKeyChecking yes, and other name mismatches
If your ~/.ssh/config, /etc/ssh/ssh_config or a file in /etc/ssh/ssh_config.d/ sets StrictHostKeyChecking yes, ssh never adds keys automatically, even in a terminal. That is a sound setting for servers; add the key with the method from cause 1.
The saved entry must also match the name you connect with. Entries are stored per host name, per IP and per port, so these are three different hosts to ssh:
ssh server.example.com
ssh 203.0.113.10
ssh -p 2222 server.example.com # stored as [server.example.com]:2222
Check whether an entry exists for exactly the name you use (works with hashed files too):
ssh-keygen -F server.example.com
ssh-keygen -F '[server.example.com]:2222'
For automation where the host list changes and keys cannot be pre-distributed, a per-host accept-new is a reasonable compromise: it saves unknown keys but still refuses changed ones.
Host build-*.internal.example.com
StrictHostKeyChecking accept-new
Tool-specific notes
- Git: Git calls ssh, so every fix above applies.
GIT_SSH_COMMAND="ssh -v" git fetchshows the ssh debug output. See Git on Linux for setup. - Ansible: it uses the controller user's known_hosts. Keep
host_key_checkingenabled and pre-populate known_hosts (for example with theknown_hostsmodule) rather than disabling it inansible.cfg. - rsync, scp, sftp: same mechanism; test with
ssh user@hostfirst, as the user that runs the job. - VS Code Remote-SSH: it uses your normal
~/.ssh/known_hosts; connecting once in a terminal fixes it.
Distro notes
The client is OpenSSH on all major distributions, so the behaviour is the same on Ubuntu, Debian and Mint (openssh-client), Fedora (openssh-clients), Arch (openssh) and openSUSE (openssh-clients). Debian and Ubuntu set HashKnownHosts yes in /etc/ssh/ssh_config, so known_hosts entries look like |1|... and you cannot grep for host names; use ssh-keygen -F host and ssh-keygen -R host instead. Fedora, Arch and openSUSE store plain host names by default.
On Fedora and openSUSE Leap 16 with SELinux enforcing, a known_hosts file created by root for another account can carry the wrong label; restorecon -Rv ~/.ssh fixes it.
How to prevent it
- Keep a verified
known_hostsfile for your Git hosts and servers and deploy it with your configuration management or CI secrets. - Run deploy and backup jobs as one dedicated user and accept keys as that user.
- Use
Hostblocks in~/.ssh/configso you always connect with the same name and port; the SSH cheat sheet lists the options. - Never put
StrictHostKeyChecking noin a global config. Useaccept-newon specific hosts only.
Once the host key is accepted, the next possible failure is authentication itself: see Permission denied (publickey) and setting up SSH keys.
Frequently asked questions
How do I fix Host key verification failed with git clone?
Connect once interactively with ssh -T [email protected] (or your Git host), compare the fingerprint with the one the host publishes, and type yes. The key is saved to ~/.ssh/known_hosts and git works afterwards.
Is it safe to set StrictHostKeyChecking no?
No. It makes ssh accept any key, including an attacker's, so it removes the protection against man-in-the-middle attacks. Use StrictHostKeyChecking accept-new for a specific host if you must automate first contact, or better, pre-load verified keys.
Why does it work as my user but fail with sudo?
With sudo, ssh runs as root and reads /root/.ssh/known_hosts, which does not contain the key you accepted as your user. Run git or ssh without sudo, or add the key to root's file or to /etc/ssh/ssh_known_hosts.
What is the difference from REMOTE HOST IDENTIFICATION HAS CHANGED?
If that big warning appears above the error, the saved key no longer matches the server, which needs a different fix. If you only see Host key verification failed, the key is usually missing from known_hosts and ssh could not ask you to accept it.
Spotted a mistake or a command that no longer works? Send a correction — pages are re-checked when reports come in.