1---
2title: Credentials
3category: Concepts
4layout: default
5SPDX-License-Identifier: LGPL-2.1-or-later
6---
7
8# System and Service Credentials
9
10The `systemd` service manager supports a "credential" concept for securely
11acquiring and passing credential data to systems and services. The precise
12nature of the credential data is up to applications, but the concept is
13intended to provide systems and services with potentially security sensitive
14cryptographic keys, certificates, passwords, identity information and similar
15types of information. It may also be used as generic infrastructure for
16parameterizing systems and services.
17
18Traditionally, data of this nature has often been provided to services via
19environment variables (which is problematic because by default they are
20inherited down the process tree, have size limitations, and issues with binary
21data) or simple, unencrypted files on disk. `systemd`'s system and service
22credentials are supposed to provide a better alternative for this
23purpose. Specifically, the following features are provided:
24
251. Service credentials are acquired at the moment of service activation, and
26   released on service deactivation. They are immutable during the service
27   runtime.
28
292. Service credentials are accessible to service code as regular files, the
30   path to access them is derived from the environment variable
31   `$CREDENTIALS_DIRECTORY`.
32
333. Access to credentials is restricted to the service's user. Unlike
34   environment variables the credential data is not propagated down the process
35   tree. Instead each time a credential is accessed an access check is enforced
36   by the kernel. If the service is using file system namespacing the loaded
37   credential data is invisible to any other services.
38
394. Service credentials may be acquired from files on disk, specified as literal
40   strings in unit files, acquired from another service dynamically via an
41   `AF_UNIX` socket, or inherited from the system credentials the system itself
42   received.
43
445. Credentials may optionally be encrypted and authenticated, either with a key
45   derived from a local TPM2 chip, or one stored in `/var/`, or both. This
46   encryption is supposed to *just* *work*, and requires no manual setup. (That
47   is besides first encrypting relevant credentials with one simple command,
48   see below.)
49
506. Service credentials are placed in non-swappable memory. (If permissions
51   allow it, via `ramfs`.)
52
537. Credentials may be acquired from a hosting VM hypervisor (qemu `fw_cfg`), a
54   hosting container manager, the kernel command line, or from the UEFI
55   environment and the EFI System Partition (via `systemd-stub`). Such system
56   credentials may then be propagated into individual services as needed.
57
588. Credentials are an effective way to pass parameters into services that run
59   with `RootImage=` or `RootDirectory=` and thus cannot read these resources
60   directly from the host directory tree.
61   Specifically, [Portable Services](PORTABLE_SERVICES.md) may be
62   parameterized this way securely and robustly.
63
649. Credentials can be binary and relatively large (though currently an overall
65   size limit of 1M per service is enforced).
66
67## Configuring per-Service Credentials
68
69Within unit files, there are four settings to configure service credentials.
70
711. `LoadCredential=` may be used to load a credential from disk, from an
72   `AF_UNIX` socket, or propagate them from a system credential.
73
742. `SetCredential=` may be used to set a credential to a literal string encoded
75   in the unit file. Because unit files are world-readable (both on disk and
76   via D-Bus), this should only be used for credentials that aren't sensitive,
77   i.e. public keys/certificates – but not private keys.
78
793. `LoadCredentialEncrypted=` is similar to `LoadCredential=` but will load an
80   encrypted credential, and decrypt it before passing it to the service. For
81   details on credential encryption, see below.
82
834. `SetCredentialEncrypted=` is similar to `SetCredential=` but expects an
84   encrypted credential to be specified literally. Unlike `SetCredential=` it
85   is thus safe to be used even for sensitive information, because even though
86   unit files are world readable, the ciphertext included in them cannot be
87   decoded unless access to TPM2/encryption key is available.
88
89Each credential configured with these options carries a short name (suitable
90for inclusion in a filename) in the unit file, under which the invoked service
91code can then retrieve it. Each name should only be specified once.
92
93For details about these four settings [see the man
94page](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Credentials).
95
96It is a good idea to also enable mount namespacing for services that process
97credentials configured this way. If so, the runtime credential directory of the
98specific service is not visible to any other service. Use `PrivateMounts=` as
99minimal option to enable such namespacing. Note that many other sandboxing
100settings (e.g. `ProtectSystem=`, `ReadOnlyPaths=` and similar) imply
101`PrivateMounts=`, hence oftentimes it's not necessary to set this option
102explicitly.
103
104## Programming Interface from Service Code
105
106When a service is invoked with one or more credentials set it will have an
107environment variable `$CREDENTIALS_DIRECTORY` set. It contains an absolute path
108to a directory the credentials are placed in. In this directory for each
109configured credential one file is placed. In addition to the
110`$CREDENTIALS_DIRECTORY` environment variable passed to the service processes
111the `%d` specifier in unit files resolves to the service's credential
112directory.
113
114Example unit file:
115
116```
117118[Service]
119ExecStart=/usr/bin/myservice.sh
120LoadCredential=foobar:/etc/myfoobarcredential.txt
121Environment=FOOBARPATH=%d/foobar
122123```
124
125Associated service shell script `/usr/bin/myservice.sh`:
126
127```sh
128#!/bin/sh
129
130sha256sum $CREDENTIAL_PATH/foobar
131sha256sum $FOOBARPATH
132
133```
134
135A service defined like this will get the contents of the file
136`/etc/myfoobarcredential.txt` passed as credential `foobar`, which is hence
137accessible under `$CREDENTIALS_DIRECTORY/foobar`. Since we additionally pass
138the path to it as environment variable `$FOOBARPATH` the credential is also
139accessible as the path in that environment variable. When invoked, the service
140will hence show the same SHA256 hash value of `/etc/myfoobarcredential.txt`
141twice.
142
143In an ideal world, well-behaved service code would directly support credentials
144passed this way, i.e. look for `$CREDENTIALS_DIRECTORY` and load the credential
145data it needs from there. For daemons that do not support this but allow
146passing credentials via a path supplied over the command line use
147`${CREDENTIAL_PATH}` in the `ExecStart=` command line to reference the
148credentials directory. For daemons that allow passing credentials via a path
149supplied as environment variable, use the `%d` specifier in the `Environment=`
150setting to build valid paths to specific credentials.
151
152## Tools
153
154The
155[`systemd-creds`](https://www.freedesktop.org/software/systemd/man/systemd-creds.html)
156tool is provided to work with system and service credentials. It may be used to
157access and enumerate system and service credentials, or to encrypt/decrypt credentials
158(for details about the latter, see below).
159
160When invoked from service context, `systemd-creds` passed without further
161parameters will list passed credentials. The `systemd-creds cat xyz` command
162may be used to write the contents of credential `xyz` to standard output. If
163these calls are combined with the `--system` switch credentials passed to the
164system as a whole are shown, instead of the those passed to the service the
165command is invoked from.
166
167Example use:
168
169```sh
170systemd-run -P --wait -p LoadCredential=abc:/etc/hosts systemd-creds cat abc
171```
172
173This will invoke a transient service with a credential `abc` sourced from the
174system's `/etc/hosts` file. This credential is then written to standard output
175via `systemd-creds cat`.
176
177## Encryption
178
179Credentials are supposed to be useful for carrying sensitive information, such
180as cryptographic key material. For this kind of data (symmetric) encryption and
181authentication is provided to make storage of the data at rest safer. The data
182may be encrypted and authenticated with AES256-GCM. The encryption key can
183either be one derived from the local TPM2 device, or one stored in
184`/var/lib/systemd/credential.secret`, or a combination of both. If a TPM2
185device is available and `/var/` resides on persistent storage the default
186behaviour is to use the combination of both for encryption, thus ensuring that
187credentials protected this way can only be decrypted and validated on the
188local hardware and OS installation. Encrypted credentials stored on disk thus
189cannot be decrypted without access to the TPM2 chip and the aforementioned key
190file `/var/lib/systemd/credential.secret`. Moreover, credentials cannot be
191prepared on another machine than the local one.
192
193The `systemd-creds` tool provides the commands `encrypt` and `decrypt` to
194encrypt and decrypt/authenticate credentials. Example:
195
196```sh
197systemd-creds encrypt plaintext.txt ciphertext.cred
198shred -u plaintext.txt
199systemd-run -P --wait -p LoadCredentialEncrypted=foobar:$(pwd)/ciphertext.cred systemd-creds cat foobar
200```
201
202This will first create an encrypted copy of the file `plaintext.txt` in the
203encrypted credential file `ciphertext.cred`. It then securely removes the
204source file. It then runs a transient service, that reads the encrypted file
205and passes it as decrypted credential `foobar` to the invoked service binary
206(which here is the `systemd-creds` tool, which just writes the data
207it received to standard output).
208
209Instead of storing the encrypted credential as a separate file on disk, it can
210also be embedded in the unit file. Example:
211
212```
213systemd-creds encrypt -p --name=foobar plaintext.txt -
214```
215
216This will output a `SetCredentialEncrypted=` line that can directly be used in
217a unit file. e.g.:
218
219```
220221[Service]
222ExecStart=/usr/bin/systemd-creds cat foobar
223SetCredentialEncrypted=foobar: \
224        k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAAC1lFmbWAqWZ8dCCQkAAAAAgAAAA \
225        AAAAAALACMA0AAAACAAAAAAfgAg9uNpGmj8LL2nHE0ixcycvM3XkpOCaf+9rwGscwmqRJ \
226        cAEO24kB08FMtd/hfkZBX8PqoHd/yPTzRxJQBoBsvo9VqolKdy9Wkvih0HQnQ6NkTKEdP \
227        HQ08+x8sv5sr+Mkv4ubp3YT1Jvv7CIPCbNhFtag1n5y9J7bTOKt2SQwBOAAgACwAAABIA \
228        ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAII6LvrmL60uEZcp5qnEkx \
229        SuhUjsDoXrJs0rfSWX4QAx5PwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
230        AAJt7Q9F/Gz0pBv1Lc4Dpn1WpebyBBm+vQ5N/lSKW2XSm8cONwCopxpDc7wJjXg7OTR6r \
231        xGCpIvGXLt3ibwJl81woLya2RRjIvc/R2zNm/yWzZAjiOLPih4SuHthqiX98ey8PUmZJB \
232        VGXglCZFjBx+d7eCqTIdghtp5pkDGwMJT6pjw4FfyFK2nJPawFKPAqzw9DK2iYttFeXi5 \
233        19xCfLBH9NKS/idlYXrhp+XIEtsr26s4lx5y10Goyc3qDOR3RD2cuZj0gHwV35hhhhcCz \
234        JaYytef1X/YL+7fYH5kuE4rxSksoUuA/LhtjszBeGbcbIT+O8SuvBJHLKTSHxPL8FTyk3 \
235        L4FSkEHs0rYwUIkKmnGohDdsYrMJ2fjH3yDNBP16aD1+f/Nuh75cjhUnGsDLt9K4hGg== \
236237```
238
239## Inheritance from Container Managers, Hypervisors, Kernel Command Line, or the UEFI Boot Environment
240
241Sometimes it is useful to parameterize whole systems the same way as services,
242via `systemd` credentials. In particular, it might make sense to boot a
243system with a set of credentials that are then propagated to individual
244services where they are ultimately consumed.
245
246`systemd` supports four ways to pass credentials to systems:
247
2481. A container manager may set the `$CREDENTIALS_DIRECTORY` environment
249   variable for systemd running as PID 1 in the container, the same way as
250   systemd would set it for a service it
251   invokes. [`systemd-nspawn(1)`](https://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#Credentials)'s
252   `--set-credential=` and `--load-credential=` switches implement this, in
253   order to pass arbitrary credentials from host to container payload. Also see
254   the [Container Interface](CONTAINER_INTERFACE.md)
255   documentation.
256
2572. Quite similar, qemu VMs can be invoked with `-fw_cfg
258   name=opt/io.systemd.credentials/foo,string=bar` to pass credentials from
259   host through the hypervisor into the VM. (This specific switch would set
260   credential `foo` to `bar`.)
261
2623. Credentials can also be passed into a system via the kernel command line,
263   via the `systemd.set-credential=` kernel command line option. Note though
264   that any data specified here is visible to any userspace application via
265   `/proc/cmdline`. This is hence typically not useful to pass sensitive
266   information.
267
2684. Credentials may also be passed from the UEFI environment to userspace, if
269   the
270   [`systemd-stub`](https://www.freedesktop.org/software/systemd/man/systemd-stub.html)
271   UEFI kernel stub is used. This allows placing encrypted credentials in the
272   EFI System Partition, which are then picked up by `systemd-stub` and passed
273   to the kernel and ultimately userspace where systemd receives them. This is
274   useful to implement secure parameterization of vendor-built and signed
275   initial RAM disks, as userspace can place credentials next to these EFI
276   kernels, and be sure they can be accessed securely from initrd context.
277
278Credentials passed to the system may be enumerated/displayed via `systemd-creds
279--system`. They may also be propagated down to services, via the
280`LoadCredential=` setting. Example:
281
282```
283systemd-nspawn --set-credential=mycred:supersecret -i test.raw -b
284```
285
286or
287
288```
289qemu-system-x86_64 \
290        -machine type=q35,accel=kvm,smm=on \
291        -smp 2 \
292        -m 1G \
293        -cpu host \
294        -nographic \
295        -nodefaults \
296        -serial mon:stdio \
297        -drive if=none,id=hd,file=test.raw,format=raw \
298        -device virtio-scsi-pci,id=scsi \
299        -device scsi-hd,drive=hd,bootindex=1 \
300        -fw_cfg name=opt/io.systemd.credentials/mycred,string=supersecret
301```
302
303Either of these lines will boot a disk image `test.raw`, once as container via
304`systemd-nspawn`, and once as VM via `qemu`. In each case the credential
305`mycred` is set to `supersecret`.
306
307Inside of the system invoked that way the credential may then be viewed:
308
309```sh
310systemd-creds --system cat mycred
311```
312
313Or propagated to services further down:
314
315```
316systemd-run -p LoadCredential=mycred -P --wait systemd-creds cat mycred
317```
318
319## Well-Known Credentials
320
321Various services shipped with `systemd` consume credentials for tweaking behaviour:
322
323* [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html)
324  will look for the credentials `passwd.hashed-password.<username>`,
325  `passwd.plaintext-password.<username>` and `passwd.shell.<username>` to
326  configure the password (either in UNIX hashed form, or plaintext) or shell of
327  system users created. Replace `<username>` with the system user of your
328  choice, for example `root`.
329
330* [`systemd-firstboot(1)`](https://www.freedesktop.org/software/systemd/man/systemd-firstboot.html)
331  will look for the credentials `firstboot.locale`, `firstboot.locale-messages`,
332  `firstboot.keymap`, `firstboot.timezone`, that configure locale, keymap or
333  timezone settings in case the data is not yet set in `/etc/`.
334
335In future more services are likely to gain support for consuming credentials.
336
337Example:
338
339```
340systemd-nspawn -i test.raw  \
341        --set-credential=passwd.hashed-password.root:$(mkpasswd mysecret) \
342        --set-credential=firstboot.locale:C.UTF-8 \
343        -b
344```
345
346This boots the specified disk image as `systemd-nspawn` container, and passes
347the root password `mysecret`and default locale `C.UTF-8` to use to it. This
348data is then propagated by default to `systemd-sysusers.service` and
349`systemd-firstboot.service`, where it is applied. (Note that these services
350will only do so if these settings in `/etc/` are so far unset, i.e. they only
351have an effect on *unprovisioned* systems, and will never override data already
352established in `/etc/`.) A similar line for qemu is:
353
354```
355qemu-system-x86_64 \
356        -machine type=q35,accel=kvm,smm=on \
357        -smp 2 \
358        -m 1G \
359        -cpu host \
360        -nographic \
361        -nodefaults \
362        -serial mon:stdio \
363        -drive if=none,id=hd,file=test.raw,format=raw \
364        -device virtio-scsi-pci,id=scsi \
365        -device scsi-hd,drive=hd,bootindex=1 \
366        -fw_cfg name=opt/io.systemd.credentials/passwd.hashed-password.root,string=$(mkpasswd mysecret) \
367        -fw_cfg name=opt/io.systemd.credentials/firstboot.locale,string=C.UTF-8
368```
369
370## Relevant Paths
371
372From *service* perspective the runtime path to find loaded credentials in is
373provided in the `$CREDENTIALS_DIRECTORY` environment variable.
374
375At runtime, credentials passed to the *system* are placed in
376`/run/credentials/@system/` (for regular credentials, such as those passed from
377a container manager or via qemu) and `/run/credentials/@encrypted/` (for
378credentials that must be decrypted/validated before use, such as those from
379`systemd-stub`).
380
381The `LoadCredential=` and `LoadCredentialEncrypted=` settings when configured
382with a relative source path will search for the source file to read the
383credential from automatically. Primarily, these credentials are searched among
384the credentials passed into the system. If not found there, they are searched
385in `/etc/credstore/`, `/run/credstore/`,
386`/usr/lib/credstore/`. `LoadCredentialEncrypted=` will also search
387`/etc/credstore.encrypted/` and similar directories. These directories are
388hence a great place to store credentials to load on the system.
389