Files
mesh-catalog/modules/gnome-keyring/README.md
T
jochen dc140d5345 gnome-keyring: the secret service as a module, claiming node-secret-service (hq ADR 0208, ADR 0102)
PAM lines written into login and passwd as blocks, so login unlocks the keyring
on both workstations; no daemon of its own; gcr's ssh agent named for the session
until the environment can say a runtime-directory path. Go tools unlocked, lock,
collections and ssh-keys, never reading a secret.
2026-10-04 13:10:58 +02:00

5.6 KiB

gnome-keyring

The secret service as a module (novox/hq ADR 0208, ADR 0102).

  • Installs gnome-keyring (it brings gcr-4, whose ssh agent this uses), libsecret (the client library and secret-tool) and seahorse (the keyrings' manager, for the operator).
  • Claims the mesh's node-secret-service seat (no verbs yet, ADR 0208 §2). It requires no display: the secret service is a D-Bus service, and a Wayland session uses the same module.
  • Writes the PAM lines into the stacks, never over them (ADR 0102). Each is a marked block at the end of the file; every other line stays the distribution's.
    • /etc/pam.d/login: auth optional pam_gnome_keyring.so and session optional pam_gnome_keyring.so auto_start. The login manager's stack includes login, so the password typed at the login screen unlocks the login keyring, and the login session starts the daemon.
    • /etc/pam.d/passwd: password optional pam_gnome_keyring.so, so changing the account's password changes the keyring's, and the next login still unlocks it.
  • Starts no daemon. PAM starts it at login, and D-Bus would if PAM had not.
  • Names gcr's ssh agent socket for the session, in the xinitrc slot first: SSH_AUTH_SOCK is $XDG_RUNTIME_DIR/gcr/ssh. The agent itself is gcr-ssh-agent.socket, a user unit the package enables by preset.

Tools

None reads a secret. They ask the Secret Service for names, counts and lock states, and the agent for fingerprints.

tool does
gnome_keyring_unlocked the login and default keyrings, locked or not; whether the daemon runs
gnome_keyring_lock lock a keyring now (login by default); unlocking stays the operator's
gnome_keyring_collections every keyring: id, label, locked, item count, created, changed, default
gnome_keyring_ssh_keys the agent's keys by fingerprint, size, type and comment

What it improves on what was found

  • The desktop's login unlocks the keyring. Its /etc/pam.d/login had no keyring lines, so the keyring stayed locked after every login, and a script prompted for the password to unlock it. Both workstations now get the same lines.
  • One daemon. The session's start ran gnome-keyring-daemon --start a second time, asking for an ssh component that gnome-keyring no longer has, and the window manager ran an unlock-prompt script. Both go.
  • The session has an ssh agent. The found export SSH_AUTH_SOCK exported nothing: the second daemon printed no socket. The session's processes had no agent, although gcr's was listening.

The default keyring is not the login keyring

On both workstations, measured on 2026-10-04, the default keyring, where programs store new secrets, is a second keyring, Default_keyring. The login keyring holds one item at most. PAM unlocks only the login keyring. Another keyring opens with it only if its password is stored in the login keyring ("unlock automatically"). On the desktop the login keyring was locked and the default one unlocked, which the unlock-prompt script did.

After the first login with this module: gnome_keyring_unlocked shows both. If the default keyring is still locked, choose one, once, in seahorse:

  • tick its unlock automatically when prompted;
  • or move its items into the login keyring and make that the default.

Which keyring is the default is the operator's data, never the module's.

Blockers and a proposal

SSH_AUTH_SOCK belongs in the account's environment, and ADR 0203 cannot say it yet. The value is a path under the account's runtime directory (/run/user/<uid>). ADR 0203 forbids $ in a contributed value, and no ${machine:…} fact names that directory. So today the variable reaches only the X session and what it starts, through the xinitrc slot. An ssh login, the login shell's execute and the user manager's services do not get it.

Proposed: a machine fact ${machine:account-runtime-dir}, resolved like ${machine:account-home} from the account's uid. The variable then becomes an environment contribution:

environment.variables.SSH_AUTH_SOCK = ${machine:account-runtime-dir}/gcr/ssh

The slot contribution then goes. That is a progressive insight on ADR 0203, or a small record of its own. It changes the controller's machine facts, not this module's shape.

User-scoped units (mesh-host #72). gcr-ssh-agent.socket and gnome-keyring-daemon.socket are enabled by the package's presets on both workstations, and nothing in the mesh asserts it. Once user units ship, this module should declare both enabled.

What it leaves as found

  • The keyrings themselves (~/.local/share/keyrings/): the operator's data, never touched.
  • ~/.config/i3/unlock-keyring.sh, the unlock-prompt script.

Migration (ADR 0182)

  1. On the laptop, /etc/pam.d/login already has the two lines outside any block. After the first push they are there twice. Delete the two hand-written ones, outside the # BEGIN mesh block.
  2. Once the xorg module writes the session's start, delete from your own part of ~/.xinitrc the eval $(/usr/bin/gnome-keyring-daemon --start …) line and the export SSH_AUTH_SOCK after it.
  3. Once the i3 module carries the main configuration, its exec … unlock-keyring.sh line is gone. Delete ~/.config/i3/unlock-keyring.sh.
  4. On the desktop, log in again after the first push. The keyring is unlocked by the login from then on.

Blockers

  • node-secret-service and the xinitrc slot are ADR 0208's. Until the controller knows them, mctl reads them as unknown.
  • The environment fact above, and user-scoped units (mesh-host #72).