SSH host key fingerprints and configurations
The first time you SSH into a fresh server, your terminal stops and asks you a question: The authenticity of host '203.0.113.10' can't be established. ED25519 key fingerprint is SHA256:9mYvLzQ... Are you sure you want t
The first time you SSH into a fresh server, your terminal stops and asks you a question:
The authenticity of host '203.0.113.10' can't be established. ED25519 key fingerprint is SHA256:9mYvLzQ... Are you sure you want to continue connecting (yes/no)?
Most people type yes and move on. I used to do the same. Then I stopped to think about what that yes actually means.
That fingerprint is a hash of the server's host key. It is the one thing proving the machine on the other end is the machine you think it is. The IP address proves nothing — IPs get reassigned, DNS gets pointed at the wrong place, and a network in between can answer for a host that isn't there. The fingerprint is the identity. Typing yes without checking it is trusting a stranger because they answered the door.
So my rule is simple: I check the fingerprint once, from a place I trust, before I ever type yes.
The easiest source is the provider. When I spin up a server, the cloud console shows the host key fingerprint for that instance. I copy it, compare it character for character with what the terminal shows, and only then type yes. If they don't match, I stop. No retry, no "probably fine", no clearing known_hosts and trying again. A mismatch is the whole warning system working as designed, and the correct response is to find out why before connecting.
If the console doesn't show it, I get the fingerprint a different way: ssh-keyscan from a network I already trust, or ssh-keygen -l against the public key file on the server through a channel I already verified. The point is the same — the fingerprint comes from somewhere other than the connection I'm about to trust. Checking the fingerprint against the same untrusted connection proves nothing.
Once I've verified it, SSH remembers it for me. The fingerprint goes into ~/.ssh/known_hosts on first connect, and from then on every connection is checked silently. That is the part people forget: the first yes is the only one that matters. Every connection after it is just confirming nothing changed.
And when it does change, SSH will tell you loudly — a big warning about a possible man-in-the-middle, connection refused. Most people's instinct is to delete the old line and reconnect. Sometimes that's right: I rebuilt the server, the host keys were regenerated, the fingerprint legitimately changed. But "sometimes" is doing a lot of work there. When I see that warning, I verify first. Did I actually rebuild this machine? Did the provider rotate the key? If I can't answer yes to something concrete, I don't connect until I can.
When the change is legitimate, I update the record deliberately: ssh-keygen -R hostname removes the old entry, then I verify the new fingerprint the same way I did the first time and connect. Deliberately, not by deleting the whole known_hosts file because it was faster.
The other half of this piece is the config file, and it's the boring half that saves the most mistakes. I don't type IP addresses, ports, and key paths from memory. They live in ~/.ssh/config:
Host api
HostName 203.0.113.10
User ubuntu
Port 2222
IdentityFile ~/.ssh/api_ed25519
Now ssh api is the whole command. The port can't be forgotten, the wrong key can't be offered, the username can't be mistyped. Each host gets its own block, each key its own file, and the config is the one place where all of it is written down. A new machine, a fresh checkout of my dotfiles, and I can reach every server I manage without reconstructing anything from memory.
Two settings I leave alone: StrictHostKeyChecking stays on. The accept-new middle ground looks convenient, but it turns the first connection back into an unchecked yes, which is the exact thing the fingerprint is there to prevent. And I never share one key across everything — one key per purpose, so revoking one doesn't mean re-keying the world.
None of this is advanced. It's a fingerprint check and a config file. But the fingerprint is the only moment SSH asks you to actually verify the identity of the machine you're about to hand your credentials to, and the config file is what stops the small mistakes that lead to the big ones. I check once, properly, and then I let the tooling do the watching.
I write about backend systems and the decisions hiding inside them. Follow along. Next in this series: CSS.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.