Why Linux keychain storage is session-scoped by default¶
On macOS and Windows the platform keychain persists across reboots and
this crate uses it without ceremony. On Linux the default backend is
kernel keyutils, whose entries are scoped to the session and disappear
when it ends. Reboot-persistent Linux storage requires opting in to the
linux-persistent feature.
That asymmetry is a build-time decision showing through at runtime.
The choice is between two kinds of cost¶
Linux has no single system keychain. The two realistic backends behind
the keyring crate are:
Kernel keyutils. Pure Rust talking to a kernel facility that is always present. No system libraries, no daemon, no build dependencies. Its keys live and die with the session.
freedesktop Secret Service. The thing GNOME Keyring and KWallet
implement, reached over D-Bus. Secrets persist across reboots. It pulls
in libdbus-sys, which links against system D-Bus and needs
pkg-config and libdbus-1-dev on the build host.
Neither is free. One costs persistence; the other costs the ability to build anywhere without preparation.
Why the hermetic default won¶
The deciding factor is who pays, and when.
Making Secret Service the default means every consumer of this crate
inherits a system-package requirement on their build host. Not their
runtime — their build. A container image that compiles a tool depending
on rtb-credentials would need libdbus-1-dev installed even if the
tool never stores anything in a keychain. Cross-compilation gets harder,
because now a C library has to be present for the target. CI images grow
an apt step. Every one of those costs lands on people who may not use
the keychain at all.
The failure is also a bad one to inherit. It appears at link time, from
libdbus-sys rather than from anything recognisable, in a build that
never mentioned D-Bus.
Choosing keyutils inverts that. The default build works everywhere with no system dependencies, and the cost falls only on the tools that actually need reboot-persistent Linux storage — which know they need it, and can install two packages deliberately.
There is a related benefit for security review. A crate whose default
build links no C libraries is easier to reason about, and this one keeps
#![forbid(unsafe_code)] over a dependency graph that stays pure Rust
unless somebody opts out.
Session-scoped is less limiting than it sounds¶
For a long-running service the distinction rarely matters. The secret is loaded at startup, usually from an environment variable, and the process outlives the question.
It matters for an interactive tool on a Linux desktop, where a user
stores a credential once and expects it to be there next week. That is
the case linux-persistent exists for, and it is a minority of
deployments rather than the common one — which is the other half of the
argument for making it opt-in.
What the feature does and does not buy¶
Enabling linux-persistent adds the Secret Service backend at compile
time. It does not make persistent storage available.
The backend still needs a D-Bus session bus and a running secret-service
provider such as gnome-keyring or kwallet. Headless servers,
containers and CI runners generally have none of these, and keychain
calls fail there in exactly the same way whether or not the feature was
compiled in. The feature makes persistence possible, not present.
Because Cargo features are additive across a build graph, one crate
enabling it turns it on for every consumer of rtb-credentials in that
build — and imposes the libdbus-1-dev build requirement on all of
them. A workspace cannot have one member opt in privately.
The practical consequence for servers is that keychain storage is often the wrong tool on Linux regardless of feature flags, and an environment variable is both simpler and the crate's recommended default anyway.