From 4b4f70c834b8c7fdedefdc647cc929b23b159552 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 16:53:32 +0900 Subject: [PATCH 01/13] feat(packages): add GNOME desktop apps for isDesktop Adds baobab, celluloid, cheese, eog, file-roller, gedit, gthumb, loupe, seahorse, and shotwell to the isDesktop package list. Co-Authored-By: Claude Sonnet 4.6 --- home-manager/packages/default.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/home-manager/packages/default.nix b/home-manager/packages/default.nix index 21326a611..5a74686e5 100644 --- a/home-manager/packages/default.nix +++ b/home-manager/packages/default.nix @@ -125,19 +125,26 @@ with pkgs; ] ++ lib.optionals (stdenv.isLinux && isDesktop) [ _1password-gui + baobab brightnessctl + celluloid + cheese chromium clickup cliphist code-cursor discord + eog evince ffmpeg + file-roller + gedit ghostty github-desktop gnome-disk-utility google-chrome grim + gthumb hypridle hyprlock hyprpicker @@ -146,11 +153,14 @@ with pkgs; hyprsunset libnotify linux-wallpaperengine + loupe nautilus pavucontrol playerctl rofi rofimoji + seahorse + shotwell signal-desktop slack slurp From 25c4441bfbd038d89b48124455d3185cb67f63f7 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 16:56:12 +0900 Subject: [PATCH 02/13] feat(matic): auto-unlock GPG key via GNOME Keyring on login Enable gnome-keyring and hook into greetd PAM so the GPG passphrase is cached on first login and never prompted again across reboots. Switch pinentry to pinentry-gnome3 and bump cache TTL to INT_MAX. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/default.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index d6198060a..ca22fc35c 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -434,13 +434,17 @@ inputs.nixpkgs.lib.nixosSystem { }; }; + # GNOME Keyring - auto-unlocks GPG key on login via PAM + services.gnome.gnome-keyring.enable = true; + security.pam.services.greetd.enableGnomeKeyring = true; + # GPG agent configuration services.gpg-agent = { enable = true; enableSshSupport = false; - pinentry.package = pkgs.pinentry-tty; - defaultCacheTtl = 94608000; # 3 years - maxCacheTtl = 94608000; # 3 years + pinentry.package = pkgs.pinentry-gnome3; + defaultCacheTtl = 2147483647; # max (effectively forever) + maxCacheTtl = 2147483647; # max (effectively forever) }; # GPG_TTY is set in fish shell init instead of sessionVariables From 5d170aa21c70228868cccbf9a6d5354d521f3ca1 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 17:37:10 +0900 Subject: [PATCH 03/13] chore: update --- named-hosts/matic/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index ca22fc35c..8c0c3c2e3 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -118,10 +118,14 @@ inputs.nixpkgs.lib.nixosSystem { # Thunderbolt support services.hardware.bolt.enable = true; + # GNOME Keyring - auto-unlocks GPG key on login via PAM + services.gnome.gnome-keyring.enable = true; + # Fingerprint authentication services.fprintd.enable = true; security.pam.services.greetd = { fprintAuth = true; + enableGnomeKeyring = true; }; security.pam.services.hyprlock = { fprintAuth = true; @@ -434,10 +438,6 @@ inputs.nixpkgs.lib.nixosSystem { }; }; - # GNOME Keyring - auto-unlocks GPG key on login via PAM - services.gnome.gnome-keyring.enable = true; - security.pam.services.greetd.enableGnomeKeyring = true; - # GPG agent configuration services.gpg-agent = { enable = true; From 66d07b0c2e8add86f75a8ba7f9bd2ab218f8f171 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 17:39:33 +0900 Subject: [PATCH 04/13] chore: update From 8c5618c131fac1bc1a75f96cff7c6bc7cda853cf Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:06:51 +0900 Subject: [PATCH 05/13] feat(matic): unlock GNOME Keyring via TPM2-backed systemd credential MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace empty-password approach with a systemd user service that decrypts the keyring password using a TPM2+host-bound credential at session start. Works with fingerprint login — no password prompt after reboot. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/default.nix | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 8c0c3c2e3..58863d8c1 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -438,6 +438,32 @@ inputs.nixpkgs.lib.nixosSystem { }; }; + # Auto-unlock GNOME Keyring on login via TPM2-backed credential + # Setup (run once): + # mkdir -p ~/.config/credstore.encrypted + # echo -n "your-keyring-password" | systemd-creds encrypt \ + # --name=gnome-keyring --with-key=tpm2+host \ + # - ~/.config/credstore.encrypted/gnome-keyring.cred + systemd.user.services.gnome-keyring-unlock = { + Unit = { + Description = "Unlock GNOME Keyring via TPM2 credential"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session-pre.target" ]; + }; + Service = { + Type = "oneshot"; + LoadCredentialEncrypted = "gnome-keyring:%h/.config/credstore.encrypted/gnome-keyring.cred"; + ExecStart = "${pkgs.writeShellScript "unlock-keyring" '' + cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | \ + ${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --unlock + ''}"; + RemainAfterExit = "yes"; + }; + Install = { + WantedBy = [ "graphical-session-pre.target" ]; + }; + }; + # GPG agent configuration services.gpg-agent = { enable = true; From c514f3bf24c92e799fb4c838bc8b1c188c970920 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:12:09 +0900 Subject: [PATCH 06/13] docs(matic): add README with GNOME Keyring TPM2 setup instructions Also add ConditionPathExists so the unlock service skips gracefully before the credential file has been created. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/README.md | 37 +++++++++++++++++++++++++++++++++++ named-hosts/matic/default.nix | 1 + 2 files changed, 38 insertions(+) create mode 100644 named-hosts/matic/README.md diff --git a/named-hosts/matic/README.md b/named-hosts/matic/README.md new file mode 100644 index 000000000..fc1fd44db --- /dev/null +++ b/named-hosts/matic/README.md @@ -0,0 +1,37 @@ +# matic + +Setup and operational notes for the `matic` NixOS host. + +--- + +## GNOME Keyring Auto-Unlock via TPM2 + +The system unlocks the GNOME Keyring automatically at login — including when using fingerprint auth — by storing the keyring password as a `systemd-creds` credential encrypted with the machine's TPM2 + host key. The credential can only be decrypted on this machine. + +### One-time setup + +After first running `make switch`, create the credential: + +```bash +mkdir -p ~/.config/credstore.encrypted +systemd-ask-password "Keyring password:" | systemd-creds encrypt \ + --name=gnome-keyring --with-key=tpm2+host \ + - ~/.config/credstore.encrypted/gnome-keyring.cred +``` + +Then restart the service: + +```bash +systemctl --user restart gnome-keyring-unlock.service +``` + +### How it works + +1. `services.gnome.gnome-keyring.enable` starts the keyring daemon at login. +2. `security.pam.services.greetd.enableGnomeKeyring` hooks into PAM (works for password login). +3. `systemd.user.services.gnome-keyring-unlock` decrypts the TPM2-bound credential and pipes it to `gnome-keyring-daemon --unlock` — this handles fingerprint login where PAM has no password to forward. +4. The service skips silently if the credential file does not exist yet. + +### Re-encrypting after keyring password change + +If you change your keyring password (via seahorse), re-run the setup command above to update the credential. diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 58863d8c1..645078dcb 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -449,6 +449,7 @@ inputs.nixpkgs.lib.nixosSystem { Description = "Unlock GNOME Keyring via TPM2 credential"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session-pre.target" ]; + ConditionPathExists = "%h/.config/credstore.encrypted/gnome-keyring.cred"; }; Service = { Type = "oneshot"; From 7a7875c5fd2339843d4d027e9ef7ee1d1ddb40a2 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:15:44 +0900 Subject: [PATCH 07/13] fix(matic): move keyring unlock to system service for TPM access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User services cannot access TPM/host keys — only the system manager can. Move gnome-keyring-unlock from systemd.user.services to systemd.services with User=skakinoki so the system manager decrypts the credential before dropping to the user. Credential moves to /etc/credstore.encrypted/. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/README.md | 20 ++++++++------ named-hosts/matic/default.nix | 52 +++++++++++++++++------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/named-hosts/matic/README.md b/named-hosts/matic/README.md index fc1fd44db..af30e218f 100644 --- a/named-hosts/matic/README.md +++ b/named-hosts/matic/README.md @@ -10,28 +10,30 @@ The system unlocks the GNOME Keyring automatically at login — including when u ### One-time setup -After first running `make switch`, create the credential: +After first running `make switch`, create the credential (requires sudo for TPM access): ```bash -mkdir -p ~/.config/credstore.encrypted -systemd-ask-password "Keyring password:" | systemd-creds encrypt \ - --name=gnome-keyring --with-key=tpm2+host \ - - ~/.config/credstore.encrypted/gnome-keyring.cred +sudo bash -c 'mkdir -p /etc/credstore.encrypted && \ + systemd-ask-password "Keyring password:" | \ + systemd-creds encrypt --name=gnome-keyring --with-key=tpm2+host \ + - /etc/credstore.encrypted/gnome-keyring.cred' ``` Then restart the service: ```bash -systemctl --user restart gnome-keyring-unlock.service +sudo systemctl restart gnome-keyring-unlock.service ``` ### How it works -1. `services.gnome.gnome-keyring.enable` starts the keyring daemon at login. -2. `security.pam.services.greetd.enableGnomeKeyring` hooks into PAM (works for password login). -3. `systemd.user.services.gnome-keyring-unlock` decrypts the TPM2-bound credential and pipes it to `gnome-keyring-daemon --unlock` — this handles fingerprint login where PAM has no password to forward. +1. `services.gnome.gnome-keyring.enable` starts the keyring daemon at login via PAM. +2. `security.pam.services.greetd.enableGnomeKeyring` auto-unlocks for password logins. +3. `systemd.services.gnome-keyring-unlock` runs as a **system service** (so the system manager can access the TPM) with `User=skakinoki`. It decrypts the credential and pipes it to `gnome-keyring-daemon --unlock` — covering fingerprint logins where PAM has no password to forward. 4. The service skips silently if the credential file does not exist yet. +> **Note:** The credential must be at the system path `/etc/credstore.encrypted/gnome-keyring.cred` (not in `~/.config`). User-level systemd services cannot access TPM/host keys — only the system manager can. + ### Re-encrypting after keyring password change If you change your keyring password (via seahorse), re-run the setup command above to update the credential. diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 645078dcb..cd4e5d2a0 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -121,6 +121,31 @@ inputs.nixpkgs.lib.nixosSystem { # GNOME Keyring - auto-unlocks GPG key on login via PAM services.gnome.gnome-keyring.enable = true; + # Unlock GNOME Keyring via TPM2 credential at login. + # System service so the system manager (not user manager) handles TPM decryption. + # Credential stored at /etc/credstore.encrypted/gnome-keyring.cred — create once with: + # sudo bash -c 'mkdir -p /etc/credstore.encrypted && \ + # systemd-ask-password "Keyring password:" | \ + # systemd-creds encrypt --name=gnome-keyring --with-key=tpm2+host \ + # - /etc/credstore.encrypted/gnome-keyring.cred' + systemd.services.gnome-keyring-unlock = { + description = "Unlock GNOME Keyring via TPM2 credential"; + after = [ "user@${toString 1000}.service" ]; + wantedBy = [ "user@${toString 1000}.service" ]; + unitConfig.ConditionPathExists = "/etc/credstore.encrypted/gnome-keyring.cred"; + serviceConfig = { + Type = "oneshot"; + User = username; + LoadCredentialEncrypted = "gnome-keyring:/etc/credstore.encrypted/gnome-keyring.cred"; + ExecStart = pkgs.writeShellScript "unlock-keyring" '' + export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" + cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | \ + ${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --unlock + ''; + RemainAfterExit = "yes"; + }; + }; + # Fingerprint authentication services.fprintd.enable = true; security.pam.services.greetd = { @@ -438,33 +463,6 @@ inputs.nixpkgs.lib.nixosSystem { }; }; - # Auto-unlock GNOME Keyring on login via TPM2-backed credential - # Setup (run once): - # mkdir -p ~/.config/credstore.encrypted - # echo -n "your-keyring-password" | systemd-creds encrypt \ - # --name=gnome-keyring --with-key=tpm2+host \ - # - ~/.config/credstore.encrypted/gnome-keyring.cred - systemd.user.services.gnome-keyring-unlock = { - Unit = { - Description = "Unlock GNOME Keyring via TPM2 credential"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session-pre.target" ]; - ConditionPathExists = "%h/.config/credstore.encrypted/gnome-keyring.cred"; - }; - Service = { - Type = "oneshot"; - LoadCredentialEncrypted = "gnome-keyring:%h/.config/credstore.encrypted/gnome-keyring.cred"; - ExecStart = "${pkgs.writeShellScript "unlock-keyring" '' - cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | \ - ${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --unlock - ''}"; - RemainAfterExit = "yes"; - }; - Install = { - WantedBy = [ "graphical-session-pre.target" ]; - }; - }; - # GPG agent configuration services.gpg-agent = { enable = true; From 263190b3cb25f97a53540a4ef21d1656b1058d34 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:20:44 +0900 Subject: [PATCH 08/13] fix(matic): set GNOME_KEYRING_CONTROL so --unlock connects to running daemon Without this, gnome-keyring-daemon --unlock starts a new instance instead of connecting to the PAM-started daemon at /run/user//keyring. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index cd4e5d2a0..5908a74b8 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -139,6 +139,7 @@ inputs.nixpkgs.lib.nixosSystem { LoadCredentialEncrypted = "gnome-keyring:/etc/credstore.encrypted/gnome-keyring.cred"; ExecStart = pkgs.writeShellScript "unlock-keyring" '' export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" + export GNOME_KEYRING_CONTROL="/run/user/$(id -u)/keyring" cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | \ ${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --unlock ''; From c04632768a910ac73b2212a5df4273cc4a93a136 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:31:35 +0900 Subject: [PATCH 09/13] fix(matic): unlock GNOME Keyring via direct control socket protocol gnome-keyring-daemon --unlock (v48) ignores GNOME_KEYRING_CONTROL and always starts a new instance. Replace with a Python script that speaks the control socket protocol directly: credentials byte + big-endian [oplen][op=1][pwlen][password] packet, reads [8][result] response. Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/default.nix | 53 +++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 5908a74b8..46000daf3 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -137,12 +137,53 @@ inputs.nixpkgs.lib.nixosSystem { Type = "oneshot"; User = username; LoadCredentialEncrypted = "gnome-keyring:/etc/credstore.encrypted/gnome-keyring.cred"; - ExecStart = pkgs.writeShellScript "unlock-keyring" '' - export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus" - export GNOME_KEYRING_CONTROL="/run/user/$(id -u)/keyring" - cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | \ - ${pkgs.gnome-keyring}/bin/gnome-keyring-daemon --unlock - ''; + ExecStart = + let + # Speaks the gnome-keyring control socket protocol directly. + # gnome-keyring-daemon --unlock (v48) ignores GNOME_KEYRING_CONTROL + # and always starts a new instance, so we bypass it entirely. + # + # Protocol (all big-endian): + # 1. connect to $XDG_RUNTIME_DIR/keyring/control (UNIX stream) + # 2. send \x00 — daemon reads our UID via SO_PEERCRED + # 3. send [oplen:4][op=1:4][pwlen:4][password bytes] + # where oplen = 8 + 4 + len(password) + # 4. read [8:4][result:4] — result 0 = OK + unlockPy = pkgs.writeScript "unlock-gnome-keyring.py" '' + #!${pkgs.python3}/bin/python3 + import os, socket, struct, stat, sys + + def unlock(password): + uid = os.getuid() + xdg = os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{uid}") + sock_path = os.path.join(xdg, "keyring", "control") + st = os.lstat(sock_path) + if not stat.S_ISSOCK(st.st_mode) or st.st_uid != uid: + raise RuntimeError(f"bad socket: {sock_path}") + pw = password.encode() + oplen = 8 + 4 + len(pw) + pkt = struct.pack(">II", oplen, 1) + struct.pack(">I", len(pw)) + pw + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s: + s.connect(sock_path) + s.sendall(b"\x00") + s.sendall(pkt) + resp = b"" + while len(resp) < 8: + resp += s.recv(8 - len(resp)) + _, result = struct.unpack(">II", resp) + return result + + pw = sys.stdin.readline().rstrip("\n") + result = unlock(pw) + codes = {0: "OK", 1: "DENIED", 2: "FAILED", 3: "NO_DAEMON"} + print(f"gnome-keyring unlock: {codes.get(result, result)}", flush=True) + sys.exit(0 if result == 0 else 1) + ''; + in + pkgs.writeShellScript "unlock-keyring" '' + export XDG_RUNTIME_DIR="/run/user/$(id -u)" + cat "$CREDENTIALS_DIRECTORY/gnome-keyring" | ${unlockPy} + ''; RemainAfterExit = "yes"; }; }; From 9c3274c20c7e1b29cf48acc4ed64d777c48e503c Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:33:13 +0900 Subject: [PATCH 10/13] docs(matic): update README to reflect working control socket approach Co-Authored-By: Claude Sonnet 4.6 --- named-hosts/matic/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/named-hosts/matic/README.md b/named-hosts/matic/README.md index af30e218f..9b4723f1e 100644 --- a/named-hosts/matic/README.md +++ b/named-hosts/matic/README.md @@ -29,10 +29,12 @@ sudo systemctl restart gnome-keyring-unlock.service 1. `services.gnome.gnome-keyring.enable` starts the keyring daemon at login via PAM. 2. `security.pam.services.greetd.enableGnomeKeyring` auto-unlocks for password logins. -3. `systemd.services.gnome-keyring-unlock` runs as a **system service** (so the system manager can access the TPM) with `User=skakinoki`. It decrypts the credential and pipes it to `gnome-keyring-daemon --unlock` — covering fingerprint logins where PAM has no password to forward. +3. `systemd.services.gnome-keyring-unlock` runs as a **system service** with `User=skakinoki` so the system manager handles TPM decryption. It then speaks the gnome-keyring **control socket protocol** directly to unlock the running daemon — covering fingerprint logins where PAM has no password to forward. 4. The service skips silently if the credential file does not exist yet. -> **Note:** The credential must be at the system path `/etc/credstore.encrypted/gnome-keyring.cred` (not in `~/.config`). User-level systemd services cannot access TPM/host keys — only the system manager can. +> **Note:** `gnome-keyring-daemon --unlock` (v48+) ignores `GNOME_KEYRING_CONTROL` and always starts a fresh instance. The service works around this by writing directly to `$XDG_RUNTIME_DIR/keyring/control` using the binary protocol: credentials byte + big-endian `[oplen][op=1][pwlen][password]`, reads `[8][result]`. +> +> **Note:** The credential must be at `/etc/credstore.encrypted/gnome-keyring.cred` (not `~/.config`). User-level systemd services cannot access TPM/host keys — only the system manager can. ### Re-encrypting after keyring password change From 69fd621ac87072efbfd632c5aba497da13ded0ba Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:35:07 +0900 Subject: [PATCH 11/13] chore: update From b28f48b06d2fb2a062083d9dd3534c10c31c170e Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:40:27 +0900 Subject: [PATCH 12/13] chore: update From 581b089b39dfcf9cc9e5056d475a51d0d75e28e4 Mon Sep 17 00:00:00 2001 From: Shun Kakinoki Date: Wed, 18 Mar 2026 18:47:46 +0900 Subject: [PATCH 13/13] fix(matic): add retry loop for keyring unlock on boot The service fires when user@1000 starts, but the keyring daemon may not be fully initialized yet (PAM login still in progress). Add a retry loop (10 attempts, 3s apart) that waits for the control socket and retries DENIED results. Also bump TimeoutStartSec to 60s. Co-Authored-By: Claude Opus 4.6 (1M context) --- named-hosts/matic/default.nix | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 46000daf3..c326ef810 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -136,6 +136,7 @@ inputs.nixpkgs.lib.nixosSystem { serviceConfig = { Type = "oneshot"; User = username; + TimeoutStartSec = 60; LoadCredentialEncrypted = "gnome-keyring:/etc/credstore.encrypted/gnome-keyring.cred"; ExecStart = let @@ -173,11 +174,28 @@ inputs.nixpkgs.lib.nixosSystem { _, result = struct.unpack(">II", resp) return result - pw = sys.stdin.readline().rstrip("\n") - result = unlock(pw) + import time + + pw = sys.stdin.read().rstrip("\n") codes = {0: "OK", 1: "DENIED", 2: "FAILED", 3: "NO_DAEMON"} - print(f"gnome-keyring unlock: {codes.get(result, result)}", flush=True) - sys.exit(0 if result == 0 else 1) + uid = os.getuid() + sock_path = f"/run/user/{uid}/keyring/control" + + for attempt in range(10): + # Wait for the control socket to appear (keyring daemon to start) + if not os.path.exists(sock_path): + print(f"attempt {attempt+1}: waiting for control socket...", flush=True) + time.sleep(3) + continue + result = unlock(pw) + print(f"attempt {attempt+1}: gnome-keyring unlock: {codes.get(result, result)}", flush=True) + if result == 0: + sys.exit(0) + # DENIED might mean daemon not fully ready yet, retry + time.sleep(3) + + print("gnome-keyring unlock: gave up after 10 attempts", flush=True) + sys.exit(1) ''; in pkgs.writeShellScript "unlock-keyring" ''