SSH "Host Key Verification Failed" — Changed Keys and known_hosts

SSH refuses the connection because the host's key doesn't match what you recorded before. Sometimes that's an attack; today it's usually a rebuilt server. Verify which before you delete anything.

What you'll see

Root causes

Server rebuilt / re-provisioned with a new host key

The common case: cloud VM re-created, container recreated with a new IP, or a reinstalled box. Old key in known_hosts, new key on the server.

IP/DNS reused by a different machine

DHCP or cloud IP reuse gives the address to a different server — legitimate but worth confirming out-of-band that your new server is the one answering.

Actual interception (rare but real)

The warning exists precisely for this. If you did NOT rebuild the server, do not skip verification — check with your provider console before removing keys.

Fix it

  1. Confirm the change is expected (rebuilt server?)
    # out-of-band check: provider console shows recent redeploys; then accept the new key
  2. Remove the stale key entry
    ssh-keygen -R <host-or-ip>   # prints which line it removed from known_hosts
  3. Reconnect and accept the new key (verify fingerprint out-of-band for servers you care about)
    ssh user@host   # on first connect, compare the shown fingerprint with the provider's console value
  4. Lock the key down to prevent future surprises on fleets
    # ssh-keyscan -H host >> ~/.ssh/known_hosts   (TOFU prepopulation), or use known_hosts verification via DNS SSHFP records

Field note

For ephemeral rebuild scenarios (CI, autoscaling), store host keys in config management or accept per-deploy via ssh -o StrictHostKeyChecking=accept-new — never 'no'. Fingerprint verification matters most on first connect to production: compare against the value shown in your provider's web console.

Common questions

Is it ever OK to just delete the old host key?

After you've confirmed out-of-band that the server was rebuilt or the IP legitimately changed, yes — that's the designed workflow. If nothing changed on your side, treat the warning as a genuine MITM indicator and investigate first.

How do I stop this in CI without disabling host checking?

Use StrictHostKeyChecking=accept-new for freshly provisioned hosts, and pin known_hosts explicitly for stable ones. Blanket 'no' removes your only protection against interception.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.