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.
Difficulty: ★☆☆☆☆
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 not specific to any init-system called the 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 XDG 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).
- ⚠️ Important: User-specific entries can override system-wide desktop entries with the same filename.
How do you 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. We must realize when the enabled service starts and stops to answer that. 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 manages this service without 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 old 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 needs to start as a “user service.”
#! /bin/zsh # -- Start binary for process in binary1 binary2 binary3 do nohup $process & done
Suppose we save the shell script to another path in $HOME, such as ‘~/.local/bin‘ (a standardized location but not in the $PATH by default), so when 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 using shell or Python scripts and create service dependencies similar to those in OpenRC.
That’s it; this concludes today’s tutorial and this series about service files in Nitrux.