{...}: { config.flake.modules.nixos.hardware-auth = { lib, config, pkgs, ... }: { options.azos.hardware-auth.enable = lib.mkOption { default = false; example = true; type = lib.types.bool; description = '' Enables YubiKey (U2F/FIDO2) as a "sufficient" PAM factor ahead of the password, for both sudo and login (which greetd/tuigreet substacks) -- touch the key to auth, or just type your password as normal if it's not plugged in. After enabling and rebuilding, enroll each key on the new machine (per-user, not machine-wide state, so this must be redone per machine): mkdir -p ~/.config/Yubico pamu2fcfg > ~/.config/Yubico/u2f_keys To add a second/backup key without overwriting the first: pamu2fcfg -n >> ~/.config/Yubico/u2f_keys Test with `sudo true` (touching the key) before trusting it on the greeter -- a login lockout is harder to recover from than a failed sudo in an already-open session. ''; }; config = lib.mkIf config.azos.hardware-auth.enable { # Default NixOS PAM rule ordering already tries u2f before pam_unix # (password), both "sufficient" -- so YubiKey touch wins first, # password always remains as fallback. # # Fingerprint (fprintd) is deliberately not wired up here: lauretta's # reader is a Synaptics Metallica MIS (06cb:009a), a match-on-chip # sensor unsupported by upstream libfprint. The only known fix is an # unofficial python-validity + open-fprintd stack, not packaged in # nixpkgs and fragile enough (suspend/resume, PAM lockout risk) to not # be worth it for now. security.pam.u2f = { enable = true; settings.cue = true; }; }; }; }