asker allows daemons to ask for user input.
<./nix/nixos-module.nix> provides options for the asker system.
An asker configuration has several keys, which are different inputs that can be requested by name.
A key can be requested by calling asker KEY.
<./nix/home-manager-module.nix> provides options for asker-prompt.
asker-prompt runs as a user service so that it can create windows.
When a key is requested, asker-prompt creates a graphical dialog that describes the request and asks for input.
For each key there is a corresponding group named asker-key-{KEY}.
asker KEY creates a request in a way that only members of the asker-key-{KEY} group can read the response.
Read more about the implementation in the design notes.
- https://github.com/LightAndLight/personal-configs/blob/533bc27168fc155b56ed055294b9feda06308733/system/sync.nix#L54-L59 (configure
askerin NixOS) - https://github.com/LightAndLight/personal-configs/blob/533bc27168fc155b56ed055294b9feda06308733/system/sync.nix#L63 (add system service's user to an
askerkey's group) - https://github.com/LightAndLight/personal-configs/blob/533bc27168fc155b56ed055294b9feda06308733/system/sync.nix#L77 (request a key)
- https://github.com/LightAndLight/personal-configs/blob/533bc27168fc155b56ed055294b9feda06308733/users/isaac/default.nix#L32 (enable
asker-promptinhome-manager)
I run Syncthing to keep my KeepassXC in sync across devices.
At the same time I have syncthing-merge running to handle any conflicts due to concurrent database edits.
It calls keepassxc-cli merge to merge conflicting databases, which requires my database password.
syncthing-merge runs as a system service under its own user,
so I wasn't able to use a graphical dialog program like zenity to ask for the password.
My solution is to run a user service that can create graphical dialogs in response to requests from system daemons,
while enforcing minimal access to the data that the user enters.
I looked into using existing keyring programs via the D-Bus Secret Service API, but I couldn't figure out how to control access to individual secrets. I know exactly which services should be allowed to access particular secrets, and I want to enforce that. In particular, I don't want my logged-in user to have universal access to these secrets, because then any program I run can read them (see also: recent discussion of this issue on Hacker News). I also found that these keyring programs aren't suited for ephemeral data; they store secrets for a while.
It might be possible to achieve this using pure D-Bus with access control policies. I haven't looked into this because after I decided that the Secret Service API was insufficient, I figured that rolling my own protocol would be easier than learning D-Bus.