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``` 117… 118[Service] 119ExecStart=/usr/bin/myservice.sh 120LoadCredential=foobar:/etc/myfoobarcredential.txt 121Environment=FOOBARPATH=%d/foobar 122… 123``` 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``` 220… 221[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== \ 236… 237``` 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