How do I add ~/bin to PATH for a systemd service?

You could hardcode the PATH in the systemd service:

[Service]
Environment=PATH=/home/someUser/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

More flexible would be PAM. It's awfully roundabout compared to simply using bash -c '....', but you can do this with PAM.

Create a new PAM configuration in /etc/pam.d (say /etc/pam.d/foo) and add:

session    required     pam_env.so user_envfile=some-file user_readenv=1

And in /home/someUser/some-file, add:

PATH DEFAULT=/home/someUser/bin:${PATH}

Of course, you can adjust the some-file name to something more sensible, but the path in user_envfile has to be relative to the user's home directory (the user that you set in User= in the service).

Then in the service file, in the [Service] section, add (foo being the file in /etc/pam.d created earlier):

PAMName=foo

Now, when you start the service (after reloading, etc.), the session modules in /etc/pam.d/foo will be run, which in this case is just pam_env. pam_env will load environment variables from /etc/environment, subject to constraints in /etc/security/pam_env.conf, and then the user environment from ~/some-file. Since PATH is set to a default value in /etc/environment, the user environment prepends to this default value.

Here, the default value of user_envfile is .pam_environment, which is also read by the PAM configuration of other things like SSH or LightDM login, etc. I used a different file here in case you don't want to affect these things. You could remove the user_envfile=... and use the default ~/.pam_environment. you could also just use an existing PAM configuration in /etc/pam.d which has user_readenv=1, but other PAM modules may cause unwanted side effects.


It seems terribly hackish, but prepending a $PATH update seems to work.
I'm on the lookout for side-effects however . . .

Example:

ExecStart=/bin/bash -c "PATH=/home/someUser/bin:$PATH exec /usr/bin/php /some/path/to/a/script.php"

In a service I was setting up (Apache Airflow) I had an Environment File set.

In my /etc/systemd/system/airflow file, I had this line:

[Service]
EnvironmentFile=/etc/default/airflow

Opening this environment file, I added the line I needed, in my case:

SCHEDULER_RUNS=5
PATH=/opt/anaconda3/bin:$PATH

Add whatever paths to the executables you need to be able to be reached by the service here and you should be ok. Worked well for me.

Tags:

Systemd