OpenRC on debian

linux
Author

Emmanuel Jeandel

Published

October 28, 2024

This post shares my experience in replacing systemd by openrc on my debian.

Why OpenRC

There are a few reasons. First, I’m not perfectly happy with systemd. It’s OK if you do nothing with it, but at some point, I had to write a specific service, and the fact that systemd does everything on your machine (hostnamed, resolvd, etc) makes it hard to just tweak just a few things. Also I don’t like journald, and I hate socket activations.

Now I decided between OpenRC and runit by looking at their features, and I like the fact that OpenRC uses dependencies for init scripts. It doesn’t come with user services, more on that later.

Installation

To make the installation as easy as possible, I booted from a rescue usb stick, chrooted into my system, and typed

aptitude install openrc

that’s it ! I tried before on virtual machines to update inside a running machine, it proved to be a mistake. Booting from a rescue CD/usb stick is much easier

The end result

Even without systemd, you will still see some systemd files and applications:

  • the udev binary is actually called systemd-udevd, because udev is now part of systemd. I have nothing against udev, and replacing it seems a bit cumbersome, so I’ll keep it for now

  • the libsystemd0 package is still installed. A few years ago it was possible to replace it with libelogind0 (ABI compatible) but the new elogind depends on libsystemd0 and conflicts with libelogind0.

An important thing to note is that getting rid of systemd does not get rid of code written in conjunction with systemd. Typically, udev is part of systemd, elogind is a fork of part of systemd

A few commands

To know the list of services that are currently run:

rc-status

Start/Stop a service

/etc/init.d/NAME [start|stop]
rc-service NAME [start|stop]

Remove a service from startup

rc-update del NAME

User services

systemd does not only manage system services, but also user services. openrc doesn’t. It turns out that there are a ton of user services that are run when someone logs on a machine: Typically, on my main desktop, 15 services (!) are launched. Some of them are pretty important and almost mandatory. Typically, I suspect that users that have a bad experience with openrc typically didn’t realize they’d need to add some users services.

A big one is pipewire, if you want to have sound. Other services are largely irrelevant, with the exception of dbus

Pipewire

To launch pipewire, 3 applications should be run: pipewire, pipewire-pulse and wireplumber

If you use a desktop environment (like KDE or gnome), an easy way to have these programs launched at startup is to create a few XDG files:

root% cat /etc/xdg/autostart/pipewire.desktop
[Desktop Entry]
Name=PipeWire
Comment=Start PipeWire
Icon=pipewire
Exec=pipewire
Terminal=false
Type=Application
NoDisplay=true
root% cat /etc/xdg/autostart/pipewire-pulse.desktop
[Desktop Entry]
Name=PipeWire pulse
Comment=Start PipeWire pulse
Icon=pipewire
Exec=pipewire-pulse
Terminal=false
Type=Application
NoDisplay=true
root% cat /etc/xdg/autostart/wireplumber.desktop 
[Desktop Entry]
Name=Wireplumber
Comment=Start Wireplumber
Icon=pipewire
Exec=wireplumber
Terminal=false
Type=Application
NoDisplay=true

The systemd services also include launching pipewire -c filter-chain.conf. I’m not sure it’s important, but if it makes a difference for you, you may add that service as well.

dbus

dbus integrates with the login daemon from systemd, which makes it so that each connection to the computer uses the same bus.

So if you launch the graphical interface, then ssh to the machine, ssh will see the bus.

This is not true with openrc, and some work needs to be done for this work.

Here are some lines to add to your shell configuration:

if [ -n "$SSH_CLIENT"  ]; then
  bus_id=$(cat /etc/machine-id)-0
  dbus_file="$HOME/.dbus/session-bus/${bus_id}"
  if [ -r "$dbus_file" ]; then
      source "$dbus_file"
      export DBUS_SESSION_BUS_ADDRESS
      export DBUS_SESSION_BUS_PID
      export DBUS_SESSION_BUS_WINDOWID      
  fi
fi

The -0 is because I’m using display :0, you can change this if relevant.

You can change all of this into export DISPLAY=:0 of course but I prefer for the variable DISPLAY to not be set.