The Strategy:
SSH relies on FIDO2 (HID). Sudo/PAM relies on OTP (HID). File encryption relies on PIV (Smart Card). We run
pcscdvia socket-activation strictly to supportage-plugin-yubikey, eliminating daemon conflicts and hardware lockups while keeping best-in-class tools.
Factory default credentials
FIDO2 has no defaults. But, PIV requires these to initialize:
PIV PIN: 123456 (Limit: 6-8 chars)PIV PUK: 12345678 (Limit: 6-8 chars)Management Key: 010203040506070801020304050607080102030405060708
Configure all your yubikeys at once
Plug in both primary and backup keys simultaneously to ensure exact mirror provisioning.
# List connected keys & serials ykman list # Prepend all commands with device target serial ykman --device 12345678 [command]
Provisioning
Execute sequentially on both keys.
Initialise PIV
# 1. Gen new Management Key (requires touch)
ykman --device [SERIAL] piv access change-management-key --generate --touch
# ^^^ SAVE OUTPUT TO PASSWORD MANAGER! ^^^
# 2. Change PIN & PUK (prompts for defaults)
ykman --device [SERIAL] piv access change-pin
ykman --device [SERIAL] piv access change-puk
Enforce “touch”
# 1. Set FIDO2 PIN (limit 63 chars)
ykman --device [SERIAL] fido access change-pin
# 2. Force PIN+touch for all passkeys
ykman --device [SERIAL] fido config toggle-always-uv
# 3. Force touch for PIV Auth (slot 9a)
ykman --device [SERIAL] piv set-touch 9a always
# 4. Force touch for PIV signing (slot 9c)
ykman --device [SERIAL] piv set-touch 9c always
Install shared PAM seed on slot-2 (optional)
Do not use
--generateif you want your backup key to unlock your OS. Generate it manually and apply it to both.
# 1. Generate a secure 40-character hex seed offline
SEED=
echo "Save this seed to your password manager: $SEED"
# (Alternative: rbw generate 40 --no-symbols if you prefer your PM CLI)
# 2. Program identical seed into both keys
ykman --device [PRIMARY_SERIAL] otp chalresp 2 $SEED --touch
ykman --device [BACKUP_SERIAL] otp chalresp 2 $SEED --touch
Reduce potential attack surface
# Disable unused physical interfaces
ykman --device [SERIAL] config nfc --disable-all
ykman --device [SERIAL] config usb --disable OPGP
# Lock config against tampering
ykman --device [SERIAL] config set-lock-code --generate
# ^^^ SAVE THIS TO PASSWORD MANAGER! ^^^
NixOS configuration
Core configuration (configuration.nix, or flake.nix)
# 1. Socket-activated smart card daemon (only runs when 'age' calls it)
services.pcscd.enable = true;
# 2. User-space USB access
services.udev.packages = [ pkgs.yubikey-personalization ];
# 3. PAM Yubico (challenge-response)
security.pam.yubico = {
enable = true;
debug = false;
mode = "challenge-response";
};
# 4. Enforce hardware touch for sudo
security.pam.services.sudo.yubicoAuth = true;
# 5. Core system packages
environment.systemPackages = with pkgs; [
yubikey-manager
pam_yubico
age
age-plugin-yubikey
];
Workflows
OS sudo authentication (OTP)
Run once to link your user account to the challenge-response seed.
mkdir -p ~/.yubico
# Queries slot 2 and saves challenge file
ykpamcfg -2 -v
SSH authentication (FIDO2)
Modern resident keys. Private key stays on hardware.
# Generate key (-O resident stores it on YubiKey)
ssh-keygen -t ed25519-sk -O resident -O verify-required -C "some@identity"
# Download public stub to a new machine. This is REQUIRED only every new machine only once.
ssh-keygen -K
File encryption (age-plugin-yubikey via PIV)
Initializes the PIV module for age. Run this for both primary and backup keys.
# Interactive setup (requires PIV PIN and Management Key)
# Make sure to say YES to requiring a physical touch!
age-plugin-yubikey --generate
# Retrieve your public identity later (if you lose it)
age-plugin-yubikey --identity
# Encrypt a file to multiple keys (so both primary and backup can decrypt)
age -r age1yubikey1_PRIMARY -r age1yubikey1_BACKUP -o secret.age secret.txt
# Decrypt (YubiKey will flash, tap to authorize)
age -d -i ~/.config/age/yubikey-identity.txt secret.age
Auditing and recovery
| Action | Target | Terminal command |
|---|---|---|
| Audit Passkeys | FIDO2 (100 (or older firmware has 25) slots) | ykman fido credentials list |
| Audit PIV Certs | Smart Card (24 slots) | ykman piv info |
| Factory Wipe FIDO2 | Destroys passkeys & SSH | ykman fido reset (8 failed PIN tries permanently locks FIDO2) |
| Recover/Wipe PIV | Resets smart card | ykman piv access unblock-pin OR ykman piv reset |