Files
Nomarchy/modules/home/keys.nix
Bernardo Magri 3757e7d66f feat(keys): SSH + GPG agent via gpg-agent, pinentry-qt
Add modules/home/keys.nix (nomarchy.keys.enable, default on): one agent —
services.gpg-agent with enableSshSupport fronts SSH, so a single pinentry
handles every passphrase (GPG signing/decryption and SSH key unlocks).
pinentry-qt for a reliable native-Wayland prompt under Hyprland, themed by
Stylix's Qt config. Cache TTLs 30 min / 2 h.

SSH_AUTH_SOCK is exported by the agent's zsh integration (terminal git/ssh
is the supported path). gnome-keyring stays the Secret Service — modern
versions run no SSH agent, so there's no socket contention; screen lock
doesn't flush the agent cache.

nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:50:45 +01:00

43 lines
1.6 KiB
Nix

# SSH + GPG agent — one agent for everything.
#
# gpg-agent fronts SSH (enableSshSupport), so a single pinentry handles
# every passphrase: GPG signing/decryption and SSH key unlocks alike. SSH
# keys are added with `ssh-add` (gpg-agent stores them by keygrip).
#
# Pinentry is pinentry-qt — reliable native-Wayland under Hyprland (no
# GNOME session to lean on) and themed by Stylix's Qt config, so the
# passphrase dialog tracks the palette.
#
# SSH_AUTH_SOCK is exported by the agent's shell integration (zsh, on via
# home.shell.enableZshIntegration in shell.nix). Terminal git/ssh is the
# supported path; a GUI client launched outside a shell won't inherit the
# socket — revisit with a session-level export if that's ever wanted.
#
# gnome-keyring (system side) stays the Secret Service for application
# secrets; modern gnome-keyring no longer runs an SSH agent, so there is no
# SSH_AUTH_SOCK contention with gpg-agent. Screen lock (hyprlock/hypridle)
# doesn't flush the agent cache — unlocked keys persist across a lock, as
# expected; the cache TTLs below govern re-prompting instead.
{ config, lib, pkgs, ... }:
let
cfg = config.nomarchy;
in
{
config = lib.mkIf cfg.keys.enable {
programs.gpg.enable = true;
services.gpg-agent = {
enable = true;
enableSshSupport = true;
pinentry.package = pkgs.pinentry-qt;
# Cache unlocked keys for a working session, then re-prompt.
defaultCacheTtl = 1800; # 30 min since last use
maxCacheTtl = 7200; # 2 h hard cap
defaultCacheTtlSsh = 1800;
maxCacheTtlSsh = 7200;
};
};
}