Skip to content
LinuxHow-To Published Updated 3 min readViews unavailable

How to Pass Secrets to systemd Services with the Credentials API

A practical systemd credentials workflow using LoadCredential, encrypted credentials, service access, rotation, permissions, and failure-safe verification.

Putting a secret directly in Environment= or on a command line spreads it into configuration exports, debugging output, process metadata, and accidental logs. systemd’s credentials API instead materializes bounded credential files for a service in a protected, service-specific directory and tells the process where to read them. This improves delivery and isolation, but the original secret still needs secure storage and rotation.

Start with a file credential

Create the source secret with restrictive ownership outside the unit file, then reference it from a drop-in:

# /etc/systemd/system/example.service.d/credentials.conf
[Service]
LoadCredential=api-token:/etc/credstore/example/api-token

Reload the manager and restart the service:

sudo systemctl daemon-reload
sudo systemctl restart example.service
sudo systemctl show example.service -p LoadCredential

The service receives a directory path in the documented credentials-directory environment variable. It should construct the path to api-token, open it as a file, bound the read size, trim only the terminator defined by the secret format, and never log the value. Shell code can use the variable, but native services should prefer the systemd helper APIs where available.

LoadCredential= does not automatically make the source file safe. Root-readable files under a dedicated credential store, external secret provisioning, or encrypted credentials each have different threat models. Avoid a source path on a user-writable or network-mounted tree that an attacker can replace before service start.

Use encrypted credentials deliberately

systemd-creds encrypt can create a credential blob sealed to supported host material and/or an explicit key, depending on options and platform capabilities. LoadCredentialEncrypted= lets the service manager decrypt that blob when activating the unit:

sudo systemd-creds encrypt \
  /etc/credstore/example/api-token \
  /etc/credstore.encrypted/example/api-token.cred

Read the installed version’s manual and choose the binding policy before relying on it for disaster recovery. A credential tied only to one machine may be intentionally unusable after motherboard replacement; a portable key must itself be protected and backed up. Encryption at rest does not protect a running service that is authorized to read the decrypted value.

Unit credentials have size limits and are designed for small opaque values, certificates, or configuration fragments—not large databases. Names become filenames, so use simple stable identifiers and avoid coupling application logic to the source path.

Harden the consumer

Run under a dedicated identity, enable an appropriate read-only file-system view, limit writable directories, remove capabilities, and restrict network access to what the service needs. Credentials avoid some secret-exposure channels; they do not stop a compromised service from using or transmitting its own secret.

Make missing credentials fatal when authentication is mandatory. An empty token should not silently select an anonymous or development mode. Use ExecStartPre= only for non-secret validation that cannot leak content; the primary process should return a precise error if the credential is absent, malformed, expired, or has an unexpected length.

Rotate and prove the full path

Write a new source or encrypted blob atomically, restart or reload the service according to its documented behavior, then verify authentication with a non-destructive real request. Credentials are generally captured for a service activation; replacing the backing file does not guarantee a long-running process rereads it.

Keep the old credential valid only for a bounded overlap, revoke it after verification, and ensure backups obey the same access policy. Test host rebuild and key loss before choosing machine-bound encryption. The finished design separates the unit’s public configuration from secret bytes and has an observable path for provisioning, activation, use, rotation, revocation, and recovery.

Related:

Sources:

Comments