What you're seeing
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
...
Host key verification failed.Sometimes shorter, sometimes longer, but the key phrase is always Host key verification failed.
What's causing this error
When you first connect to a server, SSH records the server's public host key in ~/.ssh/known_hosts. On every subsequent connection, SSH compares the server's current host key against the stored one. If they don't match, it refuses to connect — because the only reasons they wouldn't match are:
- The server was reinstalled or rebuilt. A fresh OS install generates new host keys.
- The cloud IP was reassigned. You're connecting to the same IP, but the underlying VM is now someone else's (very common with AWS Elastic IPs, DigitalOcean reserved IPs, or any rebuilt VPS).
- Host keys were intentionally rotated. Some hardening guides recommend regenerating host keys periodically.
- Man-in-the-middle attack. Someone is intercepting your traffic and presenting their own host key.
The first three are routine. The fourth is rare but the reason SSH bothers to check at all. Don't just blindly delete the old key — confirm what happened first.
How to fix it
Step 1: Confirm the change was legitimate
Before touching known_hosts, verify the new host key is what the server actually has:
- Self-managed server: SSH in via your hosting provider's web console and run
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub. Compare the fingerprint to what your client is rejecting. - AWS EC2: the host key fingerprint is in the EC2 system log (Instance → Actions → Monitor → Get system log). Look for lines starting with
ec2:. - DigitalOcean / Hetzner / Vultr: the web console shows the host key fingerprint at first boot.
- Someone else's server: ask them to verify the fingerprint over a trusted channel (Slack, signed message, phone).
If the fingerprint matches, the change is legitimate — proceed to step 2. If it doesn't match anything the server should have, stop. Don't connect. You may be the target of a MITM attack.
Step 2: Remove the stale entry from known_hosts
The clean way — surgical, only touches the one host:
$ ssh-keygen -R example.com
$ ssh-keygen -R 192.168.1.50 # also remove the IP entry if you've used oneThis removes just the entry for that host. Your other known_hosts records (and host keys you've trusted for other servers) are untouched.
Step 3: Reconnect and verify the new key
You'll see the first-connection prompt again:
The authenticity of host 'example.com (192.168.1.50)' can't be established.
ED25519 key fingerprint is SHA256:abc123...
Are you sure you want to continue connecting (yes/no)?Compare this fingerprint to the one you verified in step 1, then type yes. SSH will write the new key to known_hosts and you're done.
Common edge cases
| Situation | What's actually wrong |
|---|---|
| Error appears for a fresh AWS EC2 instance | The IP was reused. Cleanest fix: clear the old entry, verify against the system log fingerprint. |
| Multiple matching lines in known_hosts | Both hostname AND IP entries exist; run ssh-keygen -R against both. |
Error keeps coming back after ssh-keygen -R | Your known_hosts is checked in via a dotfiles repo — ssh-keygen -R modified the local file but the next checkout overwrites it. Update the repo too. |
| Connecting via a jump host / ProxyJump and you don't know which hop failed | Run ssh -v — the failing hostname is in the verbose output right before the error. |
You used StrictHostKeyChecking no and now it's failing anyway | Either the directive doesn't apply to this host block, or your known_hosts has revoked entries. Inspect with ssh-keygen -F hostname. |
| You want to skip the check for ephemeral lab environments only | Use UserKnownHostsFile /dev/null in a specific Host block in ~/.ssh/config — never globally. |
Don't do this
You'll find advice online suggesting StrictHostKeyChecking no or UserKnownHostsFile /dev/null as a "fix." These disable the check that protects you from MITM attacks. For one-off cases (ephemeral CI runners, throwaway labs) they're acceptable scoped to a specific Host block. Globally, they're how data exfiltration happens.