Modern Linux distributions following the systemd ecosystem adhere to standardised filesystem hierarchies for unit files, user configuration, temporary storage, and transient state directories. When writing shell scripts, configuring automated deployment pipelines, or packaging custom daemons on Ubuntu, hardcoding absolute file paths such as /etc/systemd/system or /run/user/1000 introduces portability issues across differing distribution versions or user environments. Ubuntu includes the built-in systemd-path utility, which programmatically queries and outputs canonical system and user filesystem paths directly from the systemd runtime environment.
Understanding systemd Standard Directory Hierarchies
The systemd architecture defines distinct locations for configuration files, runtime data, and state storage depending on scope and privilege level:
- System Unit Search Paths: Directories where system services, sockets, timers, and mount units are discovered (e.g.
/lib/systemd/system,/etc/systemd/system, and/run/systemd/system). - User Unit Search Paths: Directories searched for unprivileged user services executed within a user’s systemd manager session.
- Configuration Paths: Standard base directories defined by the XDG Base Directory specification, including configuration files, data assets, and application caches.
- Temporary and State Directories: Locations designated for persistent state, runtime caches, and ephemeral session sockets.
Using systemd-path, administrators and developers can interrogate these defined directories without guessing environment variables or parsing unit configuration files manually.
Listing All Canonical Paths with systemd-path
To view a comprehensive list of all system and user path definitions supported by the local systemd installation, run systemd-path without arguments:
systemd-path
The command outputs a structured key-value list where each identifier represents a standard directory role followed by its resolved filesystem path on Ubuntu:
system-binaries: /usr/bin
system-binaries-exec: /usr/bin
system-libraries: /usr/lib
system-data: /usr/share
system-configuration: /etc
system-runtime: /run
system-state-private: /var/lib
system-state-logs: /var/log
system-state-cache: /var/cache
system-state-spool: /var/spool
user: /home/ubuntu
user-binaries: /home/ubuntu/bin
user-configuration: /home/ubuntu/.config
user-data: /home/ubuntu/.local/share
user-runtime: /run/user/1000
Querying Specific Path Identifiers
To query an individual path variable for use inside automation scripts or terminal checks, specify the path identifier as an argument. For instance, to retrieve the current user’s ephemeral runtime directory:
systemd-path user-runtime
To find the primary system configuration directory:
systemd-path system-configuration
To determine the user configuration path conforming to the XDG specification:
systemd-path user-configuration
To query where system log files are centrally aggregated:
systemd-path system-state-logs
Inspecting Unit File Search Paths
When debugging service unit discovery or creating installer scripts for custom services, determining the exact order in which systemd evaluates directories is crucial. systemd-path provides specialised identifiers for unit search paths:
To inspect the colon-delimited search path for system-level unit files:
systemd-path systemd-unit-path
This reveals the precise priority order systemd uses when resolving units, typically checking /etc/systemd/system (administrator overrides) before /run/systemd/system (runtime generated units) and /lib/systemd/system (packaged distribution units).
To inspect the search path for user-level systemd units:
systemd-path systemd-user-unit-path
Using systemd-path in Bash Scripts and Automation
Because systemd-path returns clean, unformatted strings to standard output, it integrates seamlessly into shell scripts and installation routines.
For example, to automatically install a user unit into the correct directory without hardcoding ~/.config/systemd/user:
#!/bin/bash
USER_CONFIG=$(systemd-path user-configuration)
TARGET_DIR="${USER_CONFIG}/systemd/user"
mkdir -p "$TARGET_DIR"
cp my-custom-service.service "$TARGET_DIR/"
systemctl --user daemon-reload
echo "Service installed into: $TARGET_DIR"
To locate the appropriate temporary runtime directory for an IPC Unix socket:
RUNTIME_DIR=$(systemd-path user-runtime)
SOCKET_PATH="${RUNTIME_DIR}/my-app.sock"
echo "Listening on socket at: $SOCKET_PATH"
Troubleshooting Missing Paths and User Environments
When running systemd-path across automated cron jobs, sudo sessions, or SSH commands, keep the following considerations in mind:
- Elevated Privilege Context: When running under
sudo systemd-path user-runtime, the utility resolves paths for root (e.g./run/user/0) rather than the invoking user. To query the original user’s paths, execute the command withoutsudoor inspect/run/user/$(id -u username). - Headless Logins: If a user account does not have an active login session,
user-runtimemay return a path that does not yet exist on disk. The directory is created dynamically bypam_systemdupon initial login. Useloginctl enable-linger usernameif persistent user runtime directories are required for unattended background daemons.