WRITELOOP

STORING SECRETS AS A USER WITH SYSTEMD-CREDS

I needed a way to store API keys for my pi AI agent without relying on .env files or a desktop keychain daemon. I found that systemd-creds --user does exactly that, with encryption baked in and no root required. Here is how I set it up.

2026 May 6

How I did that?

I wanted to store an API key securely on my machine so a local AI agent could read it automatically, without me having to type anything at runtime.

I didn’t want to leave the key as plaintext on disk or require any desktop keychain daemon, since the machine that will host the agent is a zimablade with EndeavourOS (arch-based distro) with no desktop environment available.

So, I discovered that the most recent versions of systemd provide a solution: systemd-creds. It encrypts the credential at rest using a host-specific key tied to your UID and machine-id, and it needs nothing beyond systemd itself.

The --user flag (available since systemd v256) means the credential is scoped to your user. Root cannot decrypt it transparently, and it lives entirely inside your home directory.

Requirements

  • systemd v256 or higher

Check your version:

systemctl --version

The first line will show something like:

systemd 256 (256.7-1-arch)

Storing the secret

Create the directory first, then encrypt the credential:

mkdir -p ~/.config/credstore

echo -n "your_api_key_here" | systemd-creds --user encrypt - ~/.config/credstore/api_key_label.cred

The - tells systemd-creds to read from stdin. The output is an encrypted binary file at ~/.config/credstore/api_key_label.cred.

IMPORTANT: use echo -n to avoid storing a trailing newline as part of the secret.

Retrieving the secret

systemd-creds --user decrypt ~/.config/credstore/api_key_label.cred -

Again, - at the end means output goes to stdout. The raw key is printed directly, with no extra formatting.

Exporting it automatically on shell login

Add this to your ~/.bashrc or ~/.zshrc:

export API_KEY_LABEL_API_KEY="$(systemd-creds --user decrypt ~/.config/credstore/api_key_label.cred -)"

Every new shell session will silently decrypt the credential and expose it as a standard environment variable. The agent then reads it with no extra configuration:

# Bash / shell script
echo $API_KEY_LABEL_API_KEY

Verify the setup is correct

# Should print the raw API key
systemd-creds --user decrypt ~/.config/credstore/api_key_label.cred -

# Should show the env var is set in the current session
echo $API_KEY_LABEL_API_KEY

# The encrypted file should exist
ls -lh ~/.config/credstore/api_key_label.cred

Important notes

  • echo -n is mandatory. Without it, the newline becomes part of the secret and will break API calls.
  • The credential is machine-bound, so copying the .cred file to another machine will not decrypt it.
  • Root cannot decrypt a --user credential transparently without explicitly passing --uid=yourusername.
  • If the systemd version is below v256, --user is not available. Check with systemctl --version.
  • The ~/.config/credstore/ path is just a convention, which means the file can live anywhere in the home directory.