/commands/ssh-protocol/remove-host-from-known-hosts
ssh-keygen -R hostname: remove a host key from known_hosts
- tool
- SSH protocol
- versions
- OpenSSH 7.x – 10.x
- os
- linux, macos, windows
ssh-keygen -R hostname deletes every key stored for hostname in ~/.ssh/known_hosts and keeps the previous file as known_hosts.old. Run it after a server was reinstalled or its host key was rotated, when ssh refuses to connect with REMOTE HOST IDENTIFICATION HAS CHANGED. The next ssh hostname asks you to accept the new key.
Remove, find and hash entries
The block builds a small known_hosts with three entries for the same key, removes two of them, and then hashes the rest. -f points at a file other than the default ~/.ssh/known_hosts:
ssh-keygen -q -t ed25519 -N '' -f hostkey
key=$(cut -d' ' -f1,2 hostkey.pub)
printf 'server.example.com %s\n[server.example.com]:2222 %s\n192.0.2.10 %s\n' "$key" "$key" "$key" > known_hosts
echo "--- find"
ssh-keygen -F server.example.com -f known_hosts | cut -c1-48
echo "--- remove"
ssh-keygen -R server.example.com -f known_hosts
ssh-keygen -R '[server.example.com]:2222' -f known_hosts
ssh-keygen -R not-there.example -f known_hosts; echo "exit $?"
echo "--- left"
cut -d' ' -f1,2 known_hosts | cut -c1-30
echo "--- hash"
ssh-keygen -H -f known_hosts 2>&1
cut -c1-3 known_hosts
ssh-keygen -F 192.0.2.10 -f known_hosts | head -1Output
--- find # Host server.example.com found: line 1 server.example.com ssh-ed25519 AAAAC3NzaC1lZDI1N --- remove # Host server.example.com found: line 1 known_hosts updated. Original contents retained as known_hosts.old # Host [server.example.com]:2222 found: line 1 known_hosts updated. Original contents retained as known_hosts.old Host not-there.example not found in known_hosts exit 0 --- left 192.0.2.10 ssh-ed25519 --- hash WARNING: known_hosts.old contains unhashed entries Delete this file to ensure privacy of hostnames known_hosts updated. Original contents retained as known_hosts.old |1| # Host 192.0.2.10 found: line 1
The [server.example.com]:2222 entry is separate from the plain one: OpenSSH stores keys for non-default ports under [host]:port, so -R server.example.com does not touch it.
Options
| Command | What it does |
|---|---|
| ssh-keygen -R HOST | Remove all keys for HOST from ~/.ssh/known_hosts; the old file becomes known_hosts.old. |
| ssh-keygen -R '[HOST]:PORT' | Remove the entry for a server on a non-standard port. |
| ssh-keygen -R 192.0.2.10 | Remove the entry stored under the IP address (ssh may record both name and IP). |
| ssh-keygen -F HOST | Print the matching lines and their line numbers, also for hashed entries. |
| ssh-keygen -H | Hash every host name in the file so it does not reveal which servers you use. |
| ssh-keygen -f FILE ... | Work on FILE instead of ~/.ssh/known_hosts. |
| ssh-keyscan HOST | Fetch the current host key of a server, to compare its fingerprint before trusting it. |
Pitfalls
- ssh may have stored the key under the IP address as well as the name. If the warning persists, run
-Rfor the IP too; the warning message names the offending line. - Hashed entries (
|1|...) cannot be searched with grep; usessh-keygen -F. After-H, ssh-keygen warns thatknown_hosts.oldstill contains the names in clear text: delete it once the new file works. - System-wide keys in
/etc/ssh/ssh_known_hostsare not changed by-Ron your user file. Edit that file as root or pass it with-f. - On Windows the file is
%USERPROFILE%\.ssh\known_hosts; the command is the same in PowerShell with the OpenSSH client.
After removing the key, connect once and compare the fingerprint ssh shows with the one the server administrator publishes (ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub on the server). The fingerprint page shows how to read both formats. For the full warning and its causes, see remote host identification has changed.
FAQ
Is it safe to remove the old key when ssh warns that the host identification has changed?
Only after you have confirmed that the server really got a new key, for example because it was reinstalled, and you have compared the new fingerprint with one obtained over a trusted channel. Otherwise the warning may be a man-in-the-middle attack.
Why does ssh-keygen -R not remove the entry for a server on port 2222?
Entries for non-standard ports are stored as [host]:port. Pass the same form, quoted so the shell leaves the brackets alone: ssh-keygen -R '[host]:2222'.
Can I just delete the line with a text editor?
Yes, the warning prints the offending file and line number. ssh-keygen -R is safer because it also finds hashed entries, which you cannot recognise by eye, and it keeps a backup in known_hosts.old.