# NixOps configuration for the hosts using Yubikeys { config, pkgs, lib, ... }: { services = { udev = { packages = [ pkgs.yubikey-personalization # A library and command line tool to personalize YubiKeys pkgs.libu2f-host # A C library and command-line tool that implements the host-side of the U2F protocol ]; extraRules = let dependencies = with pkgs; [ coreutils gnupg gawk gnugrep ]; clearYubikey = pkgs.writeScript "clear-yubikey" '' #!${pkgs.stdenv.shell} export PATH=${pkgs.lib.makeBinPath dependencies}; keygrips=$( gpg-connect-agent 'keyinfo --list' /bye 2>/dev/null \ | grep -v OK \ | awk '{if ($4 == "T") { print $3 ".key" }}') for f in $keygrips; do rm -v ~/.gnupg/private-keys-v1.d/$f done gpg --card-status 2>/dev/null 1>/dev/null || true ''; clearYubikeyUser = pkgs.writeScript "clear-yubikey-user" '' #!${pkgs.stdenv.shell} ${pkgs.sudo}/bin/sudo -u craige ${clearYubikey} ''; in '' ACTION=="add|change", SUBSYSTEM=="usb", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407", RUN+="${clearYubikeyUser}" ''; }; pcscd.enable = true; # Enable PCSC-Lite daemon }; # Additional packages used with the Yubikey environment = { systemPackages = with pkgs; [ paperkey # Store OpenPGP or GnuPG on paper pinentry_curses # GnuPG’s interface to passphrase input pinentry_qt # GnuPG’s interface to passphrase input yubikey-manager # CLI tool for configuring any YubiKey over USB yubikey-manager-qt # Configure any YubiKey over USB interfaces yubikey-personalization # Lib & CLI tool to personalize YubiKeys yubikey-personalization-gui # QT based utility to facilitate Yubikey reconfiguration yubioath-desktop # Yubikey Desktop Authenticator ]; shellInit = '' export GPG_TTY="$(tty)" gpg-connect-agent /bye export SSH_AUTH_SOCK="/run/user/$UID/gnupg/S.gpg-agent.ssh" ''; }; programs = { ssh.startAgent = false; # Disable the SSH Agent gnupg.agent = { enable = true; # Enable GPG Agent enableSSHSupport = true; # Enable SSH agent support in GnuPG agent pinentryFlavor = "qt"; }; }; }