diff --git a/README.md b/README.md index 536d440..a87ec05 100644 --- a/README.md +++ b/README.md @@ -268,53 +268,192 @@ $ sudo yum install -y gnupg2 pinentry-curses pcsc-lite pcsc-lite-libs gnupg2-smi ## NixOS -Generate a NixOS LiveCD image with the given config: +Generate an air-gapped NixOS LiveCD image with the given config: ```nix # yubikey-installer.nix -{ nixpkgs ? , system ? "x86_64-linux" } : - let - config = { pkgs, ... }: - with pkgs; { - imports = [ ]; - - boot.kernelPackages = linuxPackages_latest; - - services.pcscd.enable = true; - services.udev.packages = [ yubikey-personalization ]; + configuration = { config, lib, pkgs, ... }: + with pkgs; + let + src = fetchGit "https://github.com/drduh/YubiKey-Guide"; + + guide = "${src}/README.md"; + + contrib = "${src}/contrib"; + + drduhConfig = fetchGit "https://github.com/drduh/config"; + + gpg-conf = "${drduhConfig}/gpg.conf"; + + xserverCfg = config.services.xserver; + + pinentryFlavour = if xserverCfg.desktopManager.lxqt.enable || xserverCfg.desktopManager.plasma5.enable then + "qt" + else if xserverCfg.desktopManager.xfce.enable then + "gtk2" + else if xserverCfg.enable || config.programs.sway.enable then + "gnome3" + else + "curses"; + + # Instead of hard-coding the pinentry program, chose the appropriate one + # based on the environment of the image the user has chosen to build. + gpg-agent-conf = runCommand "gpg-agent.conf" {} '' + sed '/pinentry-program/d' ${drduhConfig}/gpg-agent.conf > $out + echo "pinentry-program ${pinentry.${pinentryFlavour}}/bin/pinentry" >> $out + ''; + + view-yubikey-guide = writeShellScriptBin "view-yubikey-guide" '' + viewer="$(type -P xdg-open || true)" + if [ -z "$viewer" ]; then + viewer="${glow}/bin/glow -p" + fi + exec $viewer "${guide}" + ''; + + shortcut = makeDesktopItem { + name = "yubikey-guide"; + icon = "${yubikey-manager-qt}/share/ykman-gui/icons/ykman.png"; + desktopName = "drduh's YubiKey Guide"; + genericName = "Guide to using YubiKey for GPG and SSH"; + comment = "Open the guide in a reader program"; + categories = [ "Documentation" ]; + exec = "${view-yubikey-guide}/bin/view-yubikey-guide"; + }; - environment.systemPackages = [ gnupg pinentry-curses pinentry-qt paperkey wget ]; + yubikey-guide = symlinkJoin { + name = "yubikey-guide"; + paths = [ view-yubikey-guide shortcut ]; + }; - programs = { - ssh.startAgent = false; - gnupg.agent = { - enable = true; - enableSSHSupport = true; + in { + nixpkgs.config = { allowBroken = true; }; + + isoImage.isoBaseName = lib.mkForce "nixos-yubikey"; + # Uncomment this to disable compression and speed up image creation time + #isoImage.squashfsCompression = "gzip -Xcompression-level 1"; + + boot.kernelPackages = linuxPackages_latest; + # Always copytoram so that, if the image is booted from, e.g., a + # USB stick, nothing is mistakenly written to persistent storage. + boot.kernelParams = [ "copytoram" ]; + # Secure defaults + boot.cleanTmpDir = true; + boot.kernel.sysctl = { "kernel.unprivileged_bpf_disabled" = 1; }; + + services.pcscd.enable = true; + services.udev.packages = [ yubikey-personalization ]; + + programs = { + ssh.startAgent = false; + gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; }; + + environment.systemPackages = [ + # Tools for backing up keys + paperkey + pgpdump + parted + cryptsetup + + # Yubico's official tools + yubikey-manager + yubikey-manager-qt + yubikey-personalization + yubikey-personalization-gui + yubico-piv-tool + yubioath-desktop + + # Testing + ent + (haskell.lib.justStaticExecutables haskellPackages.hopenpgp-tools) + + # Password generation tools + diceware + pwgen + + # Miscellaneous tools that might be useful beyond the scope of the guide + cfssl + pcsctools + + # This guide itself (run `view-yubikey-guide` on the terminal to open it + # in a non-graphical environment). + yubikey-guide + ]; + + # Disable networking so the system is air-gapped + # Comment all of these lines out if you'll need internet access + boot.initrd.network.enable = false; + networking.dhcpcd.enable = false; + networking.dhcpcd.allowInterfaces = []; + networking.interfaces = {}; + networking.firewall.enable = true; + networking.useDHCP = false; + networking.useNetworkd = false; + networking.wireless.enable = false; + networking.networkmanager.enable = lib.mkForce false; + + # Unset history so it's never stored + # Set GNUPGHOME to an ephemeral location and configure GPG with the + # guide's recommended settings. + environment.interactiveShellInit = '' + unset HISTFILE + export GNUPGHOME="/run/user/$(id -u)/gnupg" + if [ ! -d "$GNUPGHOME" ]; then + echo "Creating \$GNUPGHOME…" + install --verbose -m=0700 --directory="$GNUPGHOME" + fi + [ ! -f "$GNUPGHOME/gpg.conf" ] && cp --verbose ${gpg-conf} "$GNUPGHOME/gpg.conf" + [ ! -f "$GNUPGHOME/gpg-agent.conf" ] && cp --verbose ${gpg-agent-conf} "$GNUPGHOME/gpg-agent.conf" + echo "\$GNUPGHOME is \"$GNUPGHOME\"" + ''; + + # Copy the contents of contrib to the home directory, add a shortcut to + # the guide on the desktop, and link to the whole repo in the documents + # folder. + system.activationScripts.yubikeyGuide = let + homeDir = "/home/nixos/"; + desktopDir = homeDir + "Desktop/"; + documentsDir = homeDir + "Documents/"; + in '' + mkdir -p ${desktopDir} ${documentsDir} + chown nixos ${homeDir} ${desktopDir} ${documentsDir} + + cp -R ${contrib}/* ${homeDir} + ln -sf ${yubikey-guide}/share/applications/yubikey-guide.desktop ${desktopDir} + ln -sfT ${src} ${documentsDir}/YubiKey-Guide + ''; }; - }; - evalNixos = configuration: import { - inherit system configuration; + nixos = import { + inherit configuration; + supportedSystems = [ "x86_64-linux" ]; }; + # Choose the one you like: + #nixos-yubikey = nixos.iso_minimal; # No graphical environment + #nixos-yubikey = nixos.iso_gnome; + nixos-yubikey = nixos.iso_plasma5; + in { - iso = (evalNixos config).config.system.build.isoImage; + inherit nixos-yubikey; } ``` Build the installer and copy it to a USB drive. ```console -$ nix build -f yubikey-installer.nix --out-link installer +$ nix build -f yubikey-installer.nix -o installer nixos-yubikey $ sudo cp -v installer/iso/*.iso /dev/sdb; sync -'installer/iso/nixos-20.03.git.c438ce1-x86_64-linux.iso' -> '/dev/sdb' +'installer/iso/nixos-yubikey-22.05beta-248980.gfedcba-x86_64-linux.iso' -> '/dev/sdb' ``` -On NixOS, ensure that you have `pinentry-program /run/current-system/sw/bin/pinentry-curses` in your `$GNUPGHOME/gpg-agent.conf` before running any `gpg` commands. - +With this image, you won't need to manually create a [temporary working directory](#temporary-working-directory) or [harden the configuration](#harden-configuration), as it was done when creating the image. ## OpenBSD @@ -2864,3 +3003,4 @@ Before you unmount your backup, ask yourself if you should make another one just * https://mlohr.com/gpg-agent-forwarding/ * https://www.ingby.com/?p=293 * https://support.yubico.com/support/solutions/articles/15000027139-yubikey-5-2-3-enhancements-to-openpgp-3-4-support +* https://github.com/dhess/nixos-yubikey