Is specifier expansion performed with systemd `EnvironmentFile=`?

systemd.exec(5) indicates the following for Environment=:

Specifier expansion is performed, see the "Specifiers" section in systemd.unit(5).

systemd.exec(5) indicates the following for EnvironmentFile=:

Similar to Environment=

So, does systemd perform specifier expansion with EnvironmentFile=?

I expected so but my test under systemd 253.5 shows that no specifier expansion is performed with EnvironmentFile=.

Test with Environment=:

Expansion is performed: SECRET_FILE=/run/credentials/mycred1.service/mysecret

[root@mymachine:~]# systemctl cat mycred1.service 
# /etc/systemd/system/mycred1.service
[Unit]

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/5l0qzzkb3r3yxygdq3688fjcc18lwg3j-glibc-locales-2.37-8/lib/locale/locale-archive"
Environment="PATH=/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/bin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/bin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/bin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/bin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/bin:/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/sbin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/sbin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/sbin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/sbin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/sbin"
Environment="TZDIR=/nix/store/4faw3w020cjxvd1dnxhg73mi10wcxvpw-tzdata-2023c/share/zoneinfo"



DynamicUser=true
Environment=SECRET_FILE=%d/mysecret
ExecStart=/nix/store/wa8vcqsc5la5yxhazrq5rxmzy1y2igaj-unit-script-mycred1-start/bin/mycred1-start 
LoadCredential=mysecret:/etc/hosts


[root@mymachine:~]# cat /nix/store/wa8vcqsc5la5yxhazrq5rxmzy1y2igaj-unit-script-mycred1-start/bin/mycred1-start
#!/nix/store/7q1b1bsmxi91zci6g8714rcljl620y7f-bash-5.2-p15/bin/bash
set -e
echo SECRET_FILE=${SECRET_FILE}



[root@mymachine:~]# systemctl start mycred1.service 

[root@mymachine:~]# systemctl status mycred1.service 
○ mycred1.service
     Loaded: loaded (/etc/systemd/system/mycred1.service; linked; preset: enabled)
     Active: inactive (dead)

Jul 18 07:24:21 mymachine systemd[1]: Started mycred1.service.
Jul 18 07:24:21 mymachine mycred1-start[4110]: SECRET_FILE=/run/credentials/mycred1.service/mysecret
Jul 18 07:24:21 mymachine systemd[1]: mycred1.service: Deactivated successfully.

Test with EnvironmentFile= (specifier in file content):

Expansion is not performed: SECRET_FILE=%d/mysecret

[root@mymachine:~]# systemctl cat mycred2.service 
# /etc/systemd/system/mycred2.service
[Unit]

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/5l0qzzkb3r3yxygdq3688fjcc18lwg3j-glibc-locales-2.37-8/lib/locale/locale-archive"
Environment="PATH=/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/bin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/bin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/bin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/bin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/bin:/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/sbin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/sbin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/sbin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/sbin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/sbin"
Environment="TZDIR=/nix/store/4faw3w020cjxvd1dnxhg73mi10wcxvpw-tzdata-2023c/share/zoneinfo"



DynamicUser=true
EnvironmentFile=/nix/store/x2ybfrhf1v3g7saadggkfap1134hnkv2-mysecret
ExecStart=/nix/store/prpm62xlw5q9lnrrxjkn8wqc3l7m9njy-unit-script-mycred2-start/bin/mycred2-start 
LoadCredential=mysecret:/etc/hosts


[root@mymachine:~]# cat /nix/store/x2ybfrhf1v3g7saadggkfap1134hnkv2-mysecret
SECRET_FILE=%d/mysecret

[root@mymachine:~]# cat /nix/store/prpm62xlw5q9lnrrxjkn8wqc3l7m9njy-unit-script-mycred2-start/bin/mycred2-start
#!/nix/store/7q1b1bsmxi91zci6g8714rcljl620y7f-bash-5.2-p15/bin/bash
set -e
echo SECRET_FILE=${SECRET_FILE}



[root@mymachine:~]# systemctl start mycred2.service 

[root@mymachine:~]# systemctl status mycred2.service 
○ mycred2.service
     Loaded: loaded (/etc/systemd/system/mycred2.service; linked; preset: enabled)
     Active: inactive (dead)

Jul 18 07:25:24 mymachine systemd[1]: Started mycred2.service.
Jul 18 07:25:24 mymachine mycred2-start[4186]: SECRET_FILE=%d/mysecret
Jul 18 07:25:24 mymachine systemd[1]: mycred2.service: Deactivated successfully.

Test with EnvironmentFile= (specifier in file path):

Expansion is not performed: Failed to load environment files: No such file or directory

[root@mymachine:~]# systemctl cat mycred3.service 
# /etc/systemd/system/mycred3.service
[Unit]

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/5l0qzzkb3r3yxygdq3688fjcc18lwg3j-glibc-locales-2.37-8/lib/locale/locale-archive"
Environment="PATH=/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/bin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/bin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/bin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/bin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/bin:/nix/store/f11ibsj5vmqcy8ihfa8mzvpfs4af7cw5-coreutils-9.1/sbin:/nix/store/jvh4fbqfxwwn162k5hb8ndc4h5555wfa-findutils-4.9.0/sbin:/nix/store/rn5b13lbsslbvmmbqnqxdcagzqp4435w-gnugrep-3.7/sbin:/nix/store/w64nwxs3r6cyqgy6ssxib5i2r6k8yfc2-gnused-4.9/sbin:/nix/store/8lgs0dqh9ks1164fp4g14gq7w1ihjbf0-systemd-253.5/sbin"
Environment="TZDIR=/nix/store/4faw3w020cjxvd1dnxhg73mi10wcxvpw-tzdata-2023c/share/zoneinfo"



EnvironmentFile=%d/myenv
ExecStart=/nix/store/779g5cfp6yq0lcpd4snmikxk1bkvfh4n-unit-script-mycred3-start/bin/mycred3-start 
LoadCredential=myenv:/etc/myenv


[root@mymachine:~]# l /etc/myenv
-rw-r--r-- 1 root root 23 2023-07-18 08:33:21 /etc/myenv

[root@mymachine:~]# cat /etc/myenv
SECRET_FILE=/etc/hosts

[root@mymachine:~]# cat /nix/store/779g5cfp6yq0lcpd4snmikxk1bkvfh4n-unit-script-mycred3-start/bin/mycred3-start
#!/nix/store/7q1b1bsmxi91zci6g8714rcljl620y7f-bash-5.2-p15/bin/bash
set -e
echo SECRET_FILE=${SECRET_FILE}



[root@mymachine:~]# systemctl start mycred3.service 
Job for mycred3.service failed because of unavailable resources or another system error.
See "systemctl status mycred3.service" and "journalctl -xeu mycred3.service" for details.

[root@mymachine:~]# systemctl status mycred3.service 
× mycred3.service
     Loaded: loaded (/etc/systemd/system/mycred3.service; linked; preset: enabled)
     Active: failed (Result: resources)
         IP: 0B in, 0B out
        CPU: 0

Jul 18 08:34:59 mymachine systemd[1]: mycred3.service: Failed to load environment files: No such file or directory
Jul 18 08:34:59 mymachine systemd[1]: mycred3.service: Failed to run 'start' task: No such file or directory
Jul 18 08:34:59 mymachine systemd[1]: mycred3.service: Failed with result 'resources'.
Jul 18 08:34:59 mymachine systemd[1]: Failed to start mycred3.service.
Asked By: soliz

||

Specifier expansions are done in EnvironmentFiles, but note that specifier expansions are done on the values passed to settings. So in the case of EnvironmentFile, the values are the file paths, not the file contents.

However, specifically for %d, it maybe the case that EnvironmentFiles are read before credentials are loaded, so %d might not be a useful specifier there. Inspecting the code, at the point credentials are loaded, environment variables from files are already availablesetup_credentials() is called from the exec_child function which has a files_env argument containing the environment variables from files.

There was some discussion around making credentials available via the environment, but Lennart Poettering thinks "that’s not a safe thing since env vars are by default inherited down the tree, even when there are privilege transitions", so this might be a deliberate design choice to make the unsafe thing harder to do.

Answered By: muru
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.