From 83f259f34f67d4ed67ac193866df5a8d309c985e Mon Sep 17 00:00:00 2001 From: Ryota Date: Sat, 17 Jan 2026 02:51:59 +0000 Subject: [PATCH] fix(home-manager): improve pcscd availability check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check for /run/pcscd/pcscd.comm socket file directly instead of using systemctl, which may have D-Bus permission issues when running as a user service. The socket file is created by systemd when pcscd.socket is active and listening. Increased wait time to 6 seconds (30 iterations × 0.2s) to handle slower boot scenarios. --- modules/home-manager/sops.nix | 36 ++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/modules/home-manager/sops.nix b/modules/home-manager/sops.nix index 85209dc..725991e 100644 --- a/modules/home-manager/sops.nix +++ b/modules/home-manager/sops.nix @@ -292,11 +292,14 @@ in description = '' Whether pcscd (PC/SC Smart Card Daemon) is required for age decryption. Enable this when using hardware key plugins like age-plugin-yubikey - or age-plugin-fido2-hmac. This automatically configures the systemd - service to depend on pcscd.socket. + or age-plugin-fido2-hmac. - Note: The system must have pcscd available (usually via - `services.pcscd.enable = true` in your NixOS configuration). + This adds a pre-start check to wait for pcscd to be available before + attempting decryption. + + Note: You must also enable `services.pcscd.enable = true` in your + NixOS configuration. The pcscd service runs at the system level and + will be socket-activated when the YubiKey is accessed. ''; }; }; @@ -397,6 +400,9 @@ in ); }; + # Note: pcscd.socket is a system service, not a user service, so we cannot + # add it as a direct dependency for requirePcscd. Instead, we add a pre-start + # script that waits for pcscd to be available. systemd.user.services.sops-nix = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { Unit = { Description = "sops-nix activation"; @@ -409,14 +415,30 @@ in lib.mapAttrsToList (name: value: "'${name}=${value}'") cfg.environment ); ExecStart = script; + ExecStartPre = lib.mkIf cfg.age.requirePcscd [ + "${pkgs.writeShellScript "wait-for-pcscd" '' + # Ensure pcscd is available for YubiKey communication. + # When pcscd.socket is enabled, systemd creates /run/pcscd/pcscd.comm + # and starts pcscd.service on-demand when the socket is accessed. + + for i in $(seq 1 30); do + # Check if the pcscd socket file exists - this is the most reliable check + # and doesn't require D-Bus access + if [ -e /run/pcscd/pcscd.comm ]; then + exit 0 + fi + sleep 0.2 + done + + echo "Warning: pcscd socket not found at /run/pcscd/pcscd.comm" >&2 + echo "YubiKey decryption may fail. Ensure services.pcscd.enable = true" >&2 + ''}" + ]; }; Install.WantedBy = if cfg.gnupg.home != null then [ "graphical-session-pre.target" ] else [ "default.target" ]; }; - # Auto-configure pcscd dependency when requirePcscd is enabled - sops.age.systemdDeps = lib.mkIf cfg.age.requirePcscd [ "pcscd.socket" ]; - # Darwin: load secrets once on login launchd.agents.sops-nix = { enable = true;