According to the systemd manual (systemd.exec, etc.), plain environment variables shouldn't be used for credential management. Systemd has an entire manual page describing its options, such as LoadCredential, LoadCredentialEncrypted, SetCredential, SetCredentialEncrypted. See https://systemd.io/CREDENTIALS/ and systemd.exec manual page for a full description of the proper way to do this in systemd.
Using environment variables means processes which don't need the credentials might still inherit or have access to the variables anyway, and could cause secrets to be exposed unintentionally. I wanted to have a systemd service integrate with Bitwarden CLI, and I used SetCredentialEncrypted following the instructions in https://systemd.io/CREDENTIALS/. After a couple of tweaks (bw expects the HOME environment variable to be set), my Bitwarden master password is encrypted at rest on disk, and only my service unit has access to it to unlock my Bitwarden account.
This is how I did it. First, I wrote my Bitwarden master password to a regular file, let's call it /tmp/bwmaster.pass. On retrospect it would have been better to write this on a ramdisk, instead of Btrfs, possibly choosing /run/ (all of these commands require root access). Next, I created an encrypted copy of my master password:
# systemd-creds encrypt --pretty --name=bwmp /tmp/bwmaster.pass -
This will pretty print a SetCredentialEncrypted=bwmp blurb which you can add to the [Service] section of your systemd service unit file (directly or as an override). Here's what my output looked like:
SetCredentialEncrypted=bwmp: \
k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAADCNQBSGbmpFUpRgngAAAAAgAAAA \
AAAAAALACMA0AAAACAAAAAAfgAgCE+qUDoEpxT3155oWkncltAG6Wv+IQAEm7EwIhahpw \
gAEB8dLosK741kyXWOWXQwLRfvhx6vDf7Na6JNGNW3PQkF6TZmJsUNYsWGXLgyIbgtjkd \
0TkS0LfVOo/e6PQ32p/xfEj0b+ZGCXgtjC0Tx6sDedhU0fIfT2b+IlwBOAAgACwAAABIA \
ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAINgs66YvSM+PW+qPTnGE/ \
8Yq67HHaX5XMmymUojmugUkPwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
AAWUZXjxS/vfx0BJq8RQAAyeXdSsf7ccsz+yEcMvoUm4WYZupWzt1FW93FDsUpdyi+QID \
pqczUQ24ODMC+HP9vP7nvLHPF4uNk+iPkR5fF7Ypl5rHdcFyfm1Bqp70g
After I stored this in my service unit file, I securely deleted the temporary plaintext file:
# shred -uz /tmp/bwmaster.pass
See man shred for more details on this. When I was doing this, I was using Bitwarden to store my Borg encrypted backup credentials. I wrote the following service file:
[Unit]
Wants=network.target
After=network-online.target
[Service]
Type=oneshot
SetCredentialEncrypted=bwmp: \
k6iUCUh0RJCQyvL8k8q1UyAAAAABAAAADAAAABAAAADCNQBSGbmpFUpRgngAAAAAgAAAA \
AAAAAALACMA0AAAACAAAAAAfgAgCE+qUDoEpxT3155oWkncltAG6Wv+IQAEm7EwIhahpw \
gAEB8dLosK741kyXWOWXQwLRfvhx6vDf7Na6JNGNW3PQkF6TZmJsUNYsWGXLgyIbgtjkd \
0TkS0LfVOo/e6PQ32p/xfEj0b+ZGCXgtjC0Tx6sDedhU0fIfT2b+IlwBOAAgACwAAABIA \
ID8H3RbsT7rIBH02CIgm/Gv1ukSXO3DMHmVQkDG0wEciABAAINgs66YvSM+PW+qPTnGE/ \
8Yq67HHaX5XMmymUojmugUkPwfdFuxPusgEfTYIiCb8a/W6RJc7cMweZVCQMbTARyIAAA \
AAWUZXjxS/vfx0BJq8RQAAyeXdSsf7ccsz+yEcMvoUm4WYZupWzt1FW93FDsUpdyi+QID \
pqczUQ24ODMC+HP9vP7nvLHPF4uNk+iPkR5fF7Ypl5rHdcFyfm1Bqp70g
Environment=BWMPATH=%d/bwmp
ExecStart=/usr/local/sbin/borg.sh
There's a little more to my borg.service file, but I only included the important parts for this topic. According to the manual, there's supposed to be a $CREDENTIAL_PATH/bwmp file that can be referenced within the script, but I couldn't get it working until I also defined the BWMPATH environment variable as I did above. That may have been because the bw command (Bitwarden CLI) tool expects the HOME variable to be set, so I set it in my script (only root will run borg.sh).
Please see the systemd.exec and https://systemd.io/CREDENTIALS manuals for the specifics on how this works. The systemd-creds command will automatically use a TPMv2 chip if it is available in your system, along with the key file. I'm not sure if my system has a TPMv2 chip, it's something I will explore later.
This worked for me on Arch Linux, systemd 251.3-1 (which hasn't been updated in a week or so). If you're using a different version this may not exist.