Contents

YubiKey for Everything: SSH, GPG, FIDO2, and the Paperweight Drawer

Hardware-backed keys for the things you actually log into

Contents

I own four YubiKeys. Two are in active use; two live in what I’ve come to call the paperweight drawer, retired because I changed my mind about how to use them. That drawer is the honest part of this post. Hardware security keys are genuinely excellent, but the path to using them well is littered with dead ends, and the marketing won’t tell you which features are worth the bother. Here’s what actually earns its keep on a self-hoster’s keychain.

FIDO2: the one everyone should use first

Advertisement

If you do nothing else, register a YubiKey as a FIDO2/WebAuthn key on your email, your password manager, and your GitHub account. This is phishing-resistant second-factor authentication — the key cryptographically binds to the site’s origin, so a fake login page simply can’t relay the challenge. No app, no codes, no shared secret on a server somewhere waiting to leak. You tap the key, it proves presence, done.

Under the bonnet, the key holds a private key it generated for that specific site, and it will only sign a challenge if the origin the browser presents matches the one it registered against. A phishing page served from a lookalike domain presents the wrong origin, so the signature never happens — not because the user was clever, but because the maths refuses. That is the whole game. Every other second factor asks a tired human to notice something is off; FIDO2 removes the human from the loop entirely. It is also increasingly the basis for passwordless login (passkeys are the same WebAuthn machinery), so registering a hardware key now puts you ahead of where most services are heading anyway.

The catch is the same as it always was: register two keys everywhere, a primary and a backup, and store the backup somewhere physically separate. A single FIDO2 key with no backup is a self-inflicted lockout waiting to happen. Every service worth using lets you enrol multiple keys; use that.

Why start here rather than with SSH keys or GPG? Because the failure mode a hardware key actually defends against — someone phishing your credentials on a convincing fake login page — is the one you are most likely to meet in practice. A time-based one-time-password app is a real improvement over SMS codes, but the code it generates can still be typed into a lookalike site by a distracted human at 8am. A FIDO2 key cannot: the browser hands the key the origin, and if the origin does not match the one the key was registered against, the ceremony simply fails. There is nothing to phish. That property alone is worth more than every other feature on the device combined, which is why I recommend enrolling FIDO2 before you touch anything else.

SSH the modern way: FIDO2-backed keys, not GPG

For years the clever-clogs move was using a YubiKey’s PIV or OpenPGP applet to hold an SSH key. Since OpenSSH 8.2 there’s a much simpler path: native FIDO2 SSH keys, where the private key never leaves the hardware and a touch is required per authentication.

1
2
3
4
5
6
7
# generate a resident-capable ed25519 key backed by the YubiKey
$ ssh-keygen -t ed25519-sk -O resident -O verify-required \
    -C "smarc@workstation" -f ~/.ssh/id_ed25519_sk
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter PIN for authenticator:
Your identification has been saved in ~/.ssh/id_ed25519_sk

The -O resident flag stores a handle on the key itself, so you can recover the private-key stub on a fresh machine with ssh-keygen -K. The -O verify-required flag forces PIN and touch. Copy the .pub to your servers as usual, and every ssh now demands a physical tap — no malware can quietly use your key while you’re away from the desk.

1
2
3
4
$ ssh server.example.net
Confirm user presence for key ED25519-SK SHA256:9c4f...
# (YubiKey blinks; you touch it)
smarc@server:~$

This is strictly better than the GPG-agent-as-SSH-agent dance for most people: fewer moving parts, no keyring to corrupt, and the touch requirement is built in. If you are coming to SSH keys fresh, the mechanics of key pairs and how the server side works are covered in public/private key authentication using SSH; the FIDO2 approach here is a hardware-backed superset of that, and it slots neatly into a properly hardened Linux server setup where you have already disabled password logins and locked SSH down to keys only.

A word on resident versus non-resident keys

The -O resident flag above is a genuine convenience/security trade-off worth understanding rather than copying blindly. A resident key stores a discoverable credential on the YubiKey itself, so on a brand-new laptop you run ssh-keygen -K and the key handle is regenerated straight from the hardware — nothing to copy across. The cost is that anyone who steals the physical key and knows (or brute- forces past the retry limit) the PIN has a usable credential. A non-resident key leaves nothing discoverable on the device; the small private-key stub lives in ~/.ssh and is useless without the matching hardware, but you must copy that stub to every machine yourself. I use resident keys on the two YubiKeys I carry and non-resident for a locked-away backup. Neither is wrong; pick the one whose failure mode you would rather live with.

GPG: powerful, fiddly, and where my paperweights came from

Advertisement

The OpenPGP applet stores real GPG private keys on-card for signing commits and encrypting files. It works, and git commit signing backed by hardware is a lovely thing. But moving subkeys onto the card is a finicky one-way operation, the gpg-agent integration is fragile across OS updates, and recovering from a mistake usually means starting over. That’s how two of my keys ended up retired — I’d provisioned them for an over-engineered GPG setup I abandoned.

1
2
3
4
5
$ gpg --card-status
Reader ...........: Yubico YubiKey FIDO CCID
Signature key ....: 4F2A 9C1D 88B0 ...  ed25519
Encryption key ...: 7E1C 3A55 90DF ...  cv25519
PIN retry counter : 3 0 3

If you sign a lot of commits or run a serious email-encryption workflow, GPG on-card is worth learning. If you don’t, skip it — it’s the feature most likely to land a key in your own paperweight drawer.

The specific trap I fell into is worth spelling out so you can avoid it. Moving a subkey onto the card with keytocard is a destructive move: it deletes the on-disk copy of that subkey and leaves only the card-bound stub. If you did not first make an encrypted offline backup of the full private key, that subkey now exists in exactly one place — the card — and if the card dies, is lost, or the PIN gets locked out after too many wrong tries, the material is gone. I learned this the tedious way and had to reissue keys and re-sign a pile of commits. The correct sequence is: generate keys on an air-gapped machine, back the full keyring up to encrypted offline media, then move copies onto the card. Do it in that order and a dead YubiKey is an annoyance, not a catastrophe.

Practical setup notes

A few things I wish someone had told me:

  • Set the PINs immediately. A new key ships with default PINs; change the user PIN and the admin PIN before you provision anything, or you’ve added a shiny new attack surface.
  • Disable applets you won’t use with the YubiKey Manager. Fewer enabled interfaces means a smaller footprint.
  • Label your keys physically. Once you have more than two, you will not remember which is the backup. A label maker saved me.
  • Decide firmware policy up front. YubiKey firmware cannot be updated in the field, so if a firmware-level advisory ever affects your model, replacing the key is the only remedy. Buy from a reputable source, note the firmware version reported by the manager, and keep the receipt — this is hardware, and treating it like hardware pays off.
  • Test the recovery path before you rely on it. Lock yourself out deliberately on a throwaway account and recover with the backup key. Better to find the gap now than during a real lockout.

Troubleshooting the things that actually break

Hardware keys fail in a small, recurring set of ways. Knowing them turns a panic into a two-minute fix.

  • ssh never prompts for a touch and just hangs. Your OpenSSH is older than 8.2 and does not understand ed25519-sk keys, or the libfido2 library is missing. Check with ssh -V; on anything current it is present, but minimal server images sometimes lack the middleware. Install libfido2 and retry.
  • “Cannot download keys” from ssh-keygen -K. The key was generated without -O resident, so there is no discoverable credential to pull back. This is not a fault — it is the non-resident behaviour. You need the on-disk stub from your backup instead.
  • PIN locked out. The FIDO2 and PIV/OpenPGP applets each have their own retry counter, and exhausting it locks that applet. FIDO2 you can reset (which wipes its credentials); the OpenPGP applet needs the admin PIN or the reset code to unblock. This is precisely why the offline key backup above matters.
  • The key works on one machine but not another. Almost always a udev rules or permissions issue on Linux — the browser or ssh cannot open the USB HID device. Installing your distribution’s libu2f-udev (or equivalent) package and replugging the key usually fixes it.
  • GitHub or your provider rejects the SSH key. FIDO2 SSH keys must be enrolled as a normal SSH key and the provider must support the [email protected] key type. Every major forge does now, but a self-hosted Git server on an old OpenSSH will refuse it until upgraded.

The verdict

Worth it? For FIDO2 second factor and FIDO2-backed SSH, unreservedly yes — those two alone justify the £50 and have measurably improved my security with almost no daily friction beyond a tap. GPG on-card is for a narrower audience: commit signers and encryption diehards who don’t mind a fiddly setup. This is for anyone who manages servers or guards an email account that controls everything else. Just buy two, register both, and resist the urge to provision every applet on day one — that’s how the paperweight drawer fills up.

If I had to compress five years of fiddling into one sentence, it would be this: the value of a hardware key is almost entirely in the two boring features — phishing-resistant login and touch-required SSH — and almost none of it is in the clever applets you will spend an evening configuring and then quietly stop using. Provision the boring things well, back them up properly, and leave the rest alone until you have a concrete reason to enable it. A key that does two jobs flawlessly beats a key you have half-configured for six. Buy the second one at the same time as the first, enrol it everywhere the primary is enrolled, and put it somewhere you will still know about in two years. Do that much and you have the whole benefit with none of the drawer.

Advertisement
Advertisement
Smarc
Written by Smarc

Founder and editor of vo.rs. A lifelong tinkerer who self-hosts far more than is sensible, hardens Linux boxes for fun, and prods the latest AI tools to see what they can really do. The how-to guides here are the notes Smarc wishes had existed the first time round.