2

Is there a way to tell systemd to search in some path for services files ?

As this manpage state, the search paths are determined during compile time. So I tried to set XDG_DATA_DIRS environment variable in /etc/systemd/user.conf

Environment="XDG_DATA_DIRS=/custom/path/lib" 

But It does not work.

PS: My service is activated through DBus.

kimaNO
  • 37
  • What doesn't work? You've given no indication of what you did that didn't function in the way that you want other than editing a file. – Nasir Riley Apr 07 '22 at 00:46
  • 1
    systemd does not find my service in the custom location. I don't want to put it in /lib/share/systemd or /etc/systemd locations. systemd manpage says that it will look for units in many places including $XDG_DATA_DIRS/systemd/user but when I set this env variables as said above it does not work – kimaNO Apr 07 '22 at 01:07
  • Are you using the --system bus (usual invocation of systemd) or are you using the --user bus? If you are running sudo systemctl {start,stop} foo.service, you are running the system bus. If you are running systemctl --user {start,stop} foo.service you are running the user bus. XDG_DATA_DIRS only affects the user bus. – Stewart Apr 08 '22 at 09:27

2 Answers2

5

The --system bus

The systemd --system bus is the "normal" way to use systemd. It's the system-wide bus and is run as root. man systemd.unit describes load paths for the --system bus as:

/etc/systemd/system.control
/run/systemd/system.control
/run/systemd/transient
/run/systemd/generator.early
/etc/systemd/system          <-- local units usually go here
/run/systemd/system
/run/systemd/generator
/usr/local/lib/systemd/system
/lib/systemd/system          <-- packaged units usually go here
/run/systemd/generator.late

This man page also says:

When the variable $SYSTEMD_UNIT_PATH is set, the contents of this variable overrides the unit load path. If $SYSTEMD_UNIT_PATH ends with an empty component (":"), the usual unit load path will be appended to the contents of the variable

Setting this variable to SYSTEMD_UNIT_PATH=/my/path/: would add /my/path to the front of the load paths. However, we cannot simply run this from the command line as systemd would already be running

SYSTEMD_UNIT_PATH=/my/path: systemd

To set the environment of the systemd --system bus, we need to look at man systemd-system.conf. Then set values in these files to affect the system bus:

/etc/systemd/system.conf
/etc/systemd/system.conf.d/*.conf   <-- Install your change here
/run/systemd/system.conf.d/*.conf
/lib/systemd/system.conf.d/*.conf

In terms of what to put in this configuration, the man page descirbes:

ManagerEnvironment=
    Takes the same arguments as DefaultEnvironment=, see above. Sets 
    environment variables just for the manager process itself. In contrast 
    to user managers, these variables are not inherited by processes spawned 
    by the system manager, use DefaultEnvironment= for that. Note that these
    variables are merged into the existing environment block. In particular, 
    in case of the system manager, this includes variables set by the kernel 
    based on the kernel command line.

Therefore install this file as /etc/systemd/system.conf.d/mypath.conf:

[Manager]
ManagerEnvironment="SYSTEMD_UNIT_PATH=/my/path:"

Disclaimer: While SYSTEMD_UNIT_PATH is documented in man systemd.unit of version 250.4 on my machine, it is not documented here. That may mean that they are deprecating the feature. If SYSTEMD_UNIT_PATH is not described in the man page of your machine, then it is not yet (or no longer) supported. In that case, the only option is to create symbolic links in /etc/systemd/system/ to each of your units in whatever location they exist.

The --user bus

The systemd --user bus is something that runs for each user who is logged in. It's useful for user-backups, user mounts, launching GUIs, or other desktop-environment stuff like VNC servers. To manage units on this bus, you run systemctl --user {start,stop} ... (without sudo). man systemd.unit describes load paths for the --user bus as:

$XDG_CONFIG_HOME/.config/systemd/user.control
$XDG_RUNTIME_DIR/systemd/user.control
/run/systemd/transient
/run/systemd/generator.early
$XDG_CONFIG_HOME/.config/systemd/user or $HOME/.config/systemd/user
$XDG_CONFIG_DIRS/.config/systemd/user or /etc/xdg/systemd/user
/etc/systemd/user
$XDG_RUNTIME_DIR/systemd/user
/run/systemd/user
$XDG_RUNTIME_DIR/systemd/generator
$XDG_DATA_HOME/systemd/user or $HOME/.local/share/systemd/user
$XDG_DATA_DIRS/systemd/user or /usr/local/share/systemd/user
$dir/systemd/user for each $dir in $XDG_DATA_DIRS
/usr/local/lib/systemd/user/*
/usr/lib/systemd/user/*
$XDG_RUNTIME_DIR/systemd/generator.late/*

To set the environment of the systemd --user bus, we need to look at man systemd-user.conf. This setting values in these files to affect the user bus:

~/.config/systemd/user.conf     <-- Here if it should affect one user
/etc/systemd/user.conf
/etc/systemd/user.conf.d/*.conf <-- Here if it should affect all user buses
/run/systemd/user.conf.d/*.conf
/usr/lib/systemd/user.conf.d/*.conf

In this case, I'm not sure if we should set DefaultEnvironment= or ManagerEnvironment=, so I would set both.

[Manager]
ManagerEnvironment="XDG_DATA_DIRS=/my/path:/usr/share/gnome:/usr/local/share/:/usr/share/"
DefaultEnvironment="XDG_DATA_DIRS=/my/path:/usr/share/gnome:/usr/local/share/:/usr/share/"

Then you need to put your units in /my/path/systemd/user/

Stewart
  • 13,677
-1

I belive you have to set the $XDG_DATA_DIR not has a bashrc/profile.d environment variable but as a systemd environment variable.

I belive the first example of systemd.environment-generator does what you want. I copied it below for quick reference:

# 50-xdg-data-dirs.sh

#!/bin/sh

SPDX-License-Identifier: CC0-1.0

set the default value

XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share}"

add a directory if it exists

if [ -d /opt/foo/share ]; then XDG_DATA_DIRS="/opt/foo/share:${XDG_DATA_DIRS}" fi

write our output

echo "XDG_DATA_DIRS=${XDG_DATA_DIRS}"

Another possibility is to define the systemd variables in .conf files in either /etc/systemd/system.conf.d/ or on a per service file as described in this other SO

  • Thank you for the suggestion but this is not working either. I am still having the error : dbus-daemon: Activation via systemd failed for unit MyService.service: unit MyService.service not found. MyService.service is located in $XDG_DATA_DIRS/systemd/user/. – kimaNO Apr 07 '22 at 18:26
  • Just to be more clear, the environment variable value is intented to be used by systemd itself not the service I am activating. – kimaNO Apr 07 '22 at 18:28
  • 1
    Yes. I know that it is a variable to be used by systemd itself. @Stewart answer is actually also pointing (in much more detail and clarity than mine) that you need to instanciate them in .conf maybe the trick is ManagerEnviornment type. – edmundoferreira Apr 08 '22 at 14:21
  • yes this was what i looking for. Thank you again. – kimaNO Apr 08 '22 at 17:46