---
title: Why Linux keychain storage uses the Secret Service
description: Why the Linux backend is the freedesktop Secret Service rather than kernel keyutils, what it costs at build and run time, and why linux-persistent no longer does anything.
tags:
- explanation
- linux
- build
---
# Why Linux keychain storage uses the Secret Service
On Linux, `KeyringStore` keeps secrets in the freedesktop Secret
Service: the D-Bus API that GNOME Keyring and KWallet implement. Secrets
persist across reboots, as they do on macOS and Windows. There is no
other Linux backend and no feature that selects one.
## What earlier releases did
Until 0.6.5 these docs said the Linux default was kernel keyutils, with
the Secret Service as an opt-in behind `linux-persistent`. That stopped
being true at 0.6.0, when the crate moved to `keyring` 4. Its `v1`
feature, which this crate enabled, makes the Secret Service the default
on Linux, reached through a pure-Rust D-Bus client (zbus). The keyutils
store was compiled in but never selected. So every 0.6 release has
stored Linux secrets in the Secret Service, whatever the docs said.
The current release keeps that behaviour and changes the client
library. zbus 6 folded `zvariant` and `zbus_names` into itself, which
left the standalone crates that zbus 5 depends on flagged as
unmaintained
([RUSTSEC-2026-0370](https://rustsec.org/advisories/RUSTSEC-2026-0370),
[0371](https://rustsec.org/advisories/RUSTSEC-2026-0371),
[0372](https://rustsec.org/advisories/RUSTSEC-2026-0372)). The
Secret Service stores for `keyring` still require zbus 5, so the crate
now depends on `keyring-core` and the per-platform stores directly, and
uses the libdbus-based Secret Service store on Linux.
Both stores look items up by the same `service` and `username`
attributes, create them in the default collection with the same label,
and store the secret as the same raw bytes. A secret written by any 0.6
release is read by this one, and one written by this release is read by
an older one.
## Why not kernel keyutils
Keyutils is pure Rust and needs no daemon, which is why the docs once
described it as the hermetic default. Its entries are scoped to the
session, though, and vanish at logout or reboot.
Making it the default now would also be a silent data loss. Every
secret stored since 0.6.0 sits in the Secret Service; a build that
switched to keyutils would stop finding them, and the only symptom would
be a tool asking for credentials it already had. Keeping the backend
that has actually been in use is the change that breaks nobody.
## What the Secret Service costs
**At run time** it needs a D-Bus session bus and a running provider such
as GNOME Keyring or KWallet. A desktop session has both. Headless
servers, containers and CI runners usually have neither, and every
keychain call fails there with `CredentialError::Keychain`. That was
equally true of every 0.6 release.
**At build time** it needs a C compiler. The store links libdbus, which
is compiled from source by `libdbus-sys` and linked statically, so the
build host needs no `libdbus-1-dev` or `pkg-config`, and the binary needs
no `libdbus-1` where it runs. Building for a musl target needs a musl C
compiler such as `musl-gcc` from the `musl-tools` package.
This is a step back from a dependency graph that compiled no C on Linux.
The crate itself still forbids `unsafe` code; the C lives in
`libdbus-sys`, the same way it would in any other D-Bus client that is
not zbus.
## What `linux-persistent` means now
Nothing. It used to add the libdbus store without selecting it, and now
the libdbus store is always the Linux backend. The feature is kept as an
empty feature so manifests that name it, including rust-tool-base's
`credentials-linux-persistent`, keep resolving.
For servers the advice has not changed: keychain storage is usually the
wrong tool there, and an environment variable is both simpler and the
crate's recommended default.