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

102 lines
5.6 KiB
Markdown

# 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).