I stopped using SSH passwords three years ago. Switched to ed25519 keys, felt pretty good about it. Then my laptop got stolen from a coffee shop — lid open, session unlocked. My private key was sitting right there in ~/.ssh/, passphrase cached in the agent.
That’s when I bought my first YubiKey.
Why a Hardware Key Beats a Private Key File
Your SSH private key lives on disk. Even if it’s passphrase-protected, once the agent unlocks it, it’s in memory. Malware can dump it. A stolen laptop might still have an active agent session. Your key file can be copied without you knowing.
A YubiKey stores the private key on the hardware. It never leaves the device. Every authentication requires a physical touch. No touch, no auth. Someone steals your laptop? They still need the physical key plugged in and your finger on it.
That’s the difference between “my key is encrypted” and “my key literally cannot be extracted.”
Which YubiKey to Get
For SSH, you want a YubiKey that supports FIDO2/resident keys. Here’s what I’d recommend:
YubiKey 5C NFC — my top pick. USB-C fits modern laptops, and the NFC means you can tap it on your phone for GitHub/Google auth too. Around $55, and I genuinely think it’s the best value if you work across multiple devices. (Full disclosure: affiliate link)
If you’re on a tighter budget, the YubiKey 5 NFC (USB-A) does the same thing for about $50, just with the older port. Still a good option if your machines have USB-A.
One important note: buy two. Register both with every service. Keep one on your keychain, one locked in a drawer. If you lose your primary, you’re not locked out of everything. I learned this the hard way with a 2FA lockout that took three days to resolve.
Setting Up SSH with FIDO2 Resident Keys
You need OpenSSH 8.2+ (check with ssh -V). Most modern distros ship with this. If you’re on macOS, the built-in OpenSSH works fine since Ventura.
First, generate a resident key stored directly on the YubiKey:
ssh-keygen -t ed25519-sk -O resident -O verify-required -C "yubikey-primary"
Breaking this down:
-t ed25519-sk— uses the ed25519 algorithm backed by a security key (sk = security key)-O resident— stores the key on the YubiKey, not just a reference to it-O verify-required— requires PIN + touch every time (not just touch)-C "yubikey-primary"— label it so you know which key this is
It’ll ask you to set a PIN if you haven’t already. Pick something decent — this is your second factor alongside the physical touch.
You’ll end up with two files: id_ed25519_sk and id_ed25519_sk.pub. The private file is actually just a handle — the real private key material lives on the YubiKey. Even if someone gets this file, it’s useless without the physical hardware.
Adding the Key to Remote Servers
Same as any SSH key:
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub user@your-server
Or manually append the public key to ~/.ssh/authorized_keys on the target machine.
When you SSH in, you’ll see:
Confirm user presence for key ED25519-SK SHA256:...
User presence confirmed
That “confirm user presence” line means it’s waiting for you to physically tap the YubiKey. No tap within ~15 seconds? Connection refused. I love this — it’s impossible to accidentally leave a session auto-connecting in the background.
The Resident Key Trick: Any Machine, No Key Files
This is the feature that sold me. Because the key is resident (stored on the YubiKey itself), you can pull it onto any machine:
ssh-keygen -K
That’s it. Plug in your YubiKey, run that command, and it downloads the key handles to your current machine. Now you can SSH from a fresh laptop, a coworker’s machine, or a server — as long as you have the YubiKey plugged in.
No more syncing ~/.ssh folders across machines. No more “I need to get my key from my other laptop.” The YubiKey is the key.
Hardening sshd for Key-Only Auth
Once your YubiKey is working, lock down the server. In /etc/ssh/sshd_config:
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
Reload sshd (systemctl reload sshd) and test with a new terminal before closing your current session. I’ve locked myself out exactly once by reloading before testing. Don’t be me.
If you want to go further, you can restrict to only FIDO2 keys by requiring the sk key types in your authorized_keys entries. But for most setups, just disabling passwords is the big win.
What About Git and GitHub?
GitHub has supported security keys for SSH since late 2021. Add your id_ed25519_sk.pub in Settings → SSH Keys, same as any other key.
Every git push and git pull now requires a physical touch. It adds maybe half a second to each operation. I was worried this would be annoying — it’s actually reassuring. Every push is a conscious decision.
For your Git config, make sure you’re using the SSH URL format:
git remote set-url origin [email protected]:username/repo.git
Gotchas I Hit
Agent forwarding doesn’t work with FIDO2 keys. The touch requirement is local — you can’t forward it through an SSH jump host. If you rely on agent forwarding, you’ll need to either set up ProxyJump or keep a regular ed25519 key for jump scenarios.
macOS Sonoma has a quirk where the built-in SSH agent sometimes doesn’t prompt for the touch correctly. Fix: add SecurityKeyProvider internal to your ~/.ssh/config.
WSL2 can’t see USB devices by default. You’ll need usbipd-win to pass the YubiKey through. It works fine once set up, but the initial config is a 10-minute detour.
VMs need USB passthrough configured. In VirtualBox, add a USB filter for “Yubico YubiKey.” In QEMU/libvirt, use hostdev passthrough. This catches people off guard when they SSH from inside a VM and wonder why the key isn’t detected.
My Setup
I carry a YubiKey 5C NFC on my keychain and keep a backup YubiKey 5 Nano in my desk. The Nano stays semi-permanently in my desktop’s USB port — it’s tiny enough that it doesn’t stick out. (Full disclosure: affiliate links)
Both keys are registered on every server, GitHub, and every service that supports FIDO2. If I lose my keychain, I walk to my desk and keep working.
Total cost: about $80 for two keys. For context, that’s less than a month of most password manager premium plans, and it protects against a class of attacks that passwords simply can’t.
Should You Bother?
If you SSH into anything regularly — servers, homelabs, CI runners — yes. The setup takes 15 minutes, and the daily friction is a light tap on a USB device. The protection you get (key material that physically can’t be stolen remotely) is worth way more than the cost.
If you’re already running a homelab with TrueNAS or managing Docker containers, this is a natural next step in locking things down. Hardware keys fill the gap between “I use SSH keys” and “my infrastructure is actually secure.”
Start with one key, test it for a week, then buy the backup. You won’t go back.
Join Alpha Signal for free market intelligence — daily briefings on tech, AI, and the markets that drive them.







