From d9d68777141fddde71b1828de72c0a30a5e8e102 Mon Sep 17 00:00:00 2001 From: aaron Date: Sat, 5 Sep 2026 15:33:05 +0200 Subject: [PATCH] feature(gpg): move git from gpg-signing to ssh-signing --- modules/home-manager/git.nix | 18 +++++++++++++++++- modules/nixos/gnupg.nix | 22 +++++++++++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/modules/home-manager/git.nix b/modules/home-manager/git.nix index db23f88..2cb61b6 100644 --- a/modules/home-manager/git.nix +++ b/modules/home-manager/git.nix @@ -1,6 +1,17 @@ { config, pkgs, inputs, ... }: +let + # public half of ~/.ssh/id_ed25519, registered and verified as a signing key + # in gitea + signingKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHRhwzo1oxaT3fEySSmILKNnu9v30cfjx5G7FKpmfqeX aaron@argon"; +in { + # gitea verifies signatures against the account key, this teaches the local + # git the same trust so `git log --show-signature` resolves as well + xdg.configFile."git/allowed_signers".text = '' + aaron@0x29a.ch ${signingKey} + ''; + programs.git = { enable = true; settings = { @@ -9,9 +20,14 @@ name = "aaron"; email = "aaron@0x29a.ch"; }; + gpg.ssh.allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers"; }; signing = { - key = "7A830180A05DAC59CDE43B0677D2F5DB48184456"; + format = "ssh"; + # point at the *public* key so ssh-keygen signs through the ssh agent + # instead of reading the passphrase protected private key from disk + key = "${config.home.homeDirectory}/.ssh/id_ed25519.pub"; + signer = "${pkgs.openssh}/bin/ssh-keygen"; signByDefault = true; }; }; diff --git a/modules/nixos/gnupg.nix b/modules/nixos/gnupg.nix index 1e1f380..6e1233c 100644 --- a/modules/nixos/gnupg.nix +++ b/modules/nixos/gnupg.nix @@ -4,12 +4,28 @@ # enable gnupg agent programs.gnupg.agent = { enable = true; - enableSSHSupport = true; - pinentryPackage = pkgs.pinentry-curses; + # a graphical pinentry never grabs the tty, so a passphrase prompt can no + # longer take over a terminal that a coding agent is driving + pinentryPackage = pkgs.pinentry-qt; + settings = { + # keep the key unlocked for a full working day instead of 10 minutes, + # so signing commits asks at most once per session + default-cache-ttl = 86400; + max-cache-ttl = 86400; + # fail an unattended signature instead of blocking on a prompt forever + pinentry-timeout = 120; + }; }; - environment.systemPackages = with pkgs; [ + environment.systemPackages = with pkgs; [ gnupg + pinentry-qt + # fallback for sessions without a display, switch pinentryPackage to use it pinentry-curses + # prime the passphrase cache on demand, e.g. before an agent session + (writeShellScriptBin "gpg-unlock" '' + echo | ${config.programs.gnupg.package}/bin/gpg --clearsign --output /dev/null + echo "gpg key unlocked" + '') ]; }