Continuing with this tutorial series about service files, today, we’ll look at a simple and comparable way to make “user services” available in Nitrux. As we mentioned in the previous tutorial, OpenRC does not use or have a concept of “user services” as defined by systemd, “systemd offers users the ability to manage services under the user’s control with a per-user systemd instance, enabling users to start, stop, enable, and disable their own units.”
With that said, let’s begin.
Services as a User?
Most users are familiar with the system-wide services managed by the init-system, think your packaged Docker daemon or the PulseAudio server. Regular services on Nitrux are usually found at ‘/etc/init.d‘ and managed with root privileges. These services have one thing in common: once enabled, they start and stop with the system boot and shut down according to their runlevel.
But a “service” can be made for and entirely controlled by regular unprivileged users. We can achieve this by using a set of already standardized paths that are not specific to any init-system.
XDG Autostart Specification
What is XDG Autostart?
The Desktop Application Autostart Specification, or XDG Autostart as it’s more commonly known, is a Freedesktop specification that “defines a method for automatically starting applications during the startup of a desktop environment […].” The Autostart directories, in order of preference, are:
- User-specific: $XDG_CONFIG_HOME/autostart (‘~/.config/autostart’ by default).
- System-wide: $XDG_CONFIG_DIRS/autostart (‘/etc/xdg/autostart’ by default).
- User-specific entries can override system-wide desktop entries with the same filename.
How to use XDG Autostart to create “user services”?
You may wonder how this is comparable to the implementation in the systemd software suite. First, we should understand the real reason for having user services. To answer that, we must realize when the enabled service starts and stops. If we enable a “user service,” it starts on user login and runs as long as a session is open for that user. Once the last session dies, the service stops.
The significant advantage is that the particular user now manages this service without the need for sudo.
If we put a simple desktop launcher (.desktop) in one of these paths, for example, the user-specific ‘~/.config/autostart,’ we can manage our “service” without root privileges.
And by creating a basic shell script, we can daemonize the binary we want to use. For example, look at our tutorial on using PipeWire and Wayland in Nitrux. In it, we use a script to autostart PipeWire on login, as PipeWire needs an environment variable (XDG_RUNTIME_DIR), and it needs to start as a “user service.”
#! /bin/zsh # -- Start binary for process in binary1 binary2 binary3 do nohup $process & done
If we save the shell script to another path in $HOME such as ‘~/.local/bin‘ (which is also a standardized location, but it’s not in the $PATH by default). We create a desktop launcher in ‘~/.config/autostart‘ we are creating a functionally similar “user service.”
[Desktop Entry] Exec=$HOME/.local/bin/start-my-service Icon= Name=User service Path= Terminal=False Type=Application
This way, our “service” will start when the user logs in and stop when the user logs out, achieving the same. Furthermore, we can get creative with the shell script and create similar service dependencies as those used in OpenRC.
That’s it; this concludes today’s tutorial and this series about service files in Nitrux.