Re: First time user experiences

From: Alexis <flexibeast_at_gmail.com>
Date: Mon, 02 Mar 2026 10:59:26 +1100

Guillermo <gdiazhartusch_at_gmail.com> writes:

> What Gentoo with OpenRC has traditionally done for dealing with
> PipeWire and WirePlumber, is installing a script that tries to
> emulate
> the behaviour, and that is called by desktop environments that
> implement Freedesktop's desktop application autostart
> specification.
>
> *
> https://gitweb.gentoo.org/repo/gentoo.git/tree/media-video/pipewire/files/gentoo-pipewire-launcher.in-r4?id=20c3561947c263ea300c9e04a134910539f9c191
> * https://specifications.freedesktop.org/autostart/0.5
>
> But, with navi-desu's contributions, OpenRC added user services
> in
> version 0.60, so Gentoo now also ships corresponding OpenRC user
> service scripts.

Indeed, although at this point, it should be noted that those
specific user services are still regarded as 'experimental', and
there are some things to be aware of when using them, as i've
described in this issue i've opened:

  https://bugs.gentoo.org/970611

(i've actually contributed various fixes/improvements to the
`gentoo-pipewire-launcher` script over time,
e.g. https://bugs.gentoo.org/907891, amongst others.)

> What is missing is the tie with login sessions, which would
> probably
> require dealing with those "unsavory interfaces". That's why I
> was
> interested in what Alexis was doing.

Well, the first thing to note is that i'm using elogind, which
probably avoids certain issues. (On the Gentoo wiki, we have a
page to try to support those who don't want to use elogind,
https://wiki.gentoo.org/wiki/Configuring_a_system_without_elogind
)

Also, my user setup is - to say the least - 'unusual', in that it
has a focus on decoupling, designed to:

* help isolate issues, and;
* facilitate switching between different sorts of setups, in order
  to be better able to understand and document things for others.

i thus make no claim that how i've done things is The Way To Do
Things. :-)

With all that said:

i use Zsh as my 'daily driver' shell. In my ~/.zprofile, i have
this:

```
# Used by ~/.local/bin/start-services.sh, called by ~/.zlogin:
# # 'manual' to manually start services.
# * 's6sup' to manually start s6-supervise processes for services.
# * 's6svscan' to use s6-svscan on a scandir.
# * 's6rc' to use s6-rc services.
export USER_S6=s6rc
```

In ~/.zlogin, i have:

```
if [ $(who | wc -l) -lt 2 ]; then
    ${HOME}/.local/bin/start-services.sh
fi
```

This is to (try to) ensure i'm only running services under one
login session, so that i can log in on other VTs to do things like
test how a specific Wayland compositor works, whilst still running
my usual GUI session.

(Side note: i often try to write shell that's as close to POSIX as
possible, so that it's easier to generalise to being portable
should i decide to make it public; i've created a page on the
Gentoo wiki to help me - and hopefully others! - remember the
scripting-related differences between shells,
https://wiki.gentoo.org/wiki/Shell/Scripting )

In ~/.local/bin/start-services.sh (yes, i know i don't _need_ the
`.sh` extension; it's purely a personal reminder to me that i find
helpful):

```
#!/usr/bin/sh

#
# Script assumes XDG_* env vars and LOGS env var are set
  appropriately.
#
# Which services to start are specified as files in
# $XDG_STATE_HOME/services, each file containing a single
# line, separated by ':', consisting of three fields:
#
# * Command line to start the service manually.
# * `pgrep` option to check if service is already running.
# * Description of service.
#

SERVICES="${XDG_STATE_HOME}/services"

###
# Helper functions.
##

... [logging functions] ...

# Start services.

case ${USER_S6} in

    's6rc')

        S6RC_SERVICES="${HOME}/src/srht/s6-rc-services/sh/user"
        S6RC_WANTED="${XDG_STATE_HOME}/s6-rc/wanted"
        S6RC_COMPILED="${XDG_STATE_HOME}/s6-rc/compiled"
        S6RC_SCANDIR="${XDG_STATE_HOME}/s6-rc/scandir"
        S6RC_LIVE="${XDG_RUNTIME_DIR}/s6-rc"

        rm -f "${S6RC_WANTED}"/*
        rm -rf "${S6RC_COMPILED}"
        rm -f "${S6RC_SCANDIR}"/*
        rm -rf "${S6RC_LIVE}"*

        for s in $SERVICES/*; do
            ln -s "${S6RC_SERVICES}/$(basename $s)"
            "${S6RC_WANTED}"
            if [ -d "${S6RC_SERVICES}/$(basename $s)-log" ]
            then
                ln -s "${S6RC_SERVICES}/$(basename $s)-log"
                "${S6RC_WANTED}"
            fi
        done

        echo -n "Compiling s6-rc database in ${S6RC_COMPILED}
        .... "
        s6-rc-compile "${S6RC_COMPILED}" "${S6RC_WANTED}"
        if [ ! $? = '0' ]; then
            echo 'failed.'
        else
            echo 'ok.'
        fi
        echo -n "Starting s6-svscan on ${S6RC_SCANDIR} .... "
        s6-svscan -- "${S6RC_SCANDIR}" 1>>"${LOGS}/s6-svscan.log"
        2>&1 &
        if [ ! $? = '0' ]; then
            echo 'failed.'
        else
            echo 'ok.'
        fi
        echo -n "Initialising s6-rc with live at ${S6RC_LIVE}
        .... "
        s6-rc-init -c "${S6RC_COMPILED}" -l "${S6RC_LIVE}"
        "${S6RC_SCANDIR}"
        if [ ! $? = '0' ]; then
            echo 'failed.'
        else
            echo 'ok.'
        fi

        for s in $S6RC_SCANDIR/*; do
             echo -n "Starting $(basename $s) .... "
             s6-rc -l "${S6RC_LIVE}" start "$(basename $s)"
             if [ ! $? = '0' ]; then
                  echo 'failed.'
             else
                 echo 'ok.'
             fi
        done

        ;;

    's6svscan')

...

    *)

        echo "Unknown value for USER_S6, '${USER_S6}' - no
        services started!"
        exit 1

        ;;

esac
```

"${HOME}/src/srht/s6-rc-services/sh/user" is part of a Git repo
whose upstream is a private repo on Sourcehut, which i've not yet
set up properly due to All The Stuff Happening. :-) The `sh` in
the path is intended to be able to separate services based on
POSIX sh from services based on e.g. execline, and the `user` is
intended to separate 'user' services from 'system' services. This
was part of my idea for a public repo of s6-rc services; i'll come
back to this.

My ${XDG_STATE_HOME}/services/ directory looks like:

```
-rw-r--r-- 1 alexis alexis 0 Dec 16 2024 dbus-session-bus
-rw-r--r-- 1 alexis alexis 0 Dec 16 2024 emacs
-rw-r--r-- 1 alexis alexis 0 Dec 22 2024 mpd
-rw-r--r-- 1 alexis alexis 0 Dec 22 2024 pipewire
-rw-r--r-- 1 alexis alexis 0 Dec 22 2024 pipewire-pulse
-rw-r--r-- 1 alexis alexis 0 Dec 22 2024 wireplumber
```

where each entry has been created via touch(1), to 'activate' the
service.

We're finally at the actual services. :-P The `dbus-session-bus`
service is basically as i've described in my "OpenRC user services
via s6 and s6-rc" guide:

  https://wiki.gentoo.org/wiki/User:Flexibeast/guides/OpenRC_user_services_via_s6_and_s6-rc#An_s6-rc_D-Bus_session_bus_service

In a previous post to the list, i wrote "by default, PipeWire runs
per-user, and requires a D-Bus session bus"; what i _should_ have
written was "requires a D-Bus session bus _for my use-cases_". In
particular, i want RTKit support, which is one of the cases where
D-Bus support is required, as described in the PipeWire FAQ:

  https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#does-pipewire-require-dbussystemdflatpak

(i'm wanting to do more music production, so Linux audio is
effectively now on my 'critical path', hence my increased focus on
it, and wanting to spend less time on other stuff.)

The run files for the `pipewire`, `pipewire-pulse` and
`wireplumber` user services reflect the fact that i'd been
intending to make their behaviour configurable:

```
#!/bin/sh

if [ -f "${XDG_CONFIG_HOME}/s6-rc/pipewire" ]
then
    . "${XDG_CONFIG_HOME}/s6-rc/pipewire"
fi

exec /usr/bin/s6-notifyoncheck /usr/bin/pipewire
```

```
!/bin/sh

if [ -f "${XDG_CONFIG_HOME}/s6-rc/pipewire-pulse" ]
then
    . "${XDG_CONFIG_HOME}/s6-rc/pipewire-pulse"
fi

exec /usr/bin/s6-notifyoncheck /usr/bin/pipewire -c
pipewire-pulse.conf
```

```
#!/bin/sh

exec /usr/bin/s6-notifyoncheck /usr/bin/wireplumber
```

With all that in place, i have the following convenience functions
in my ~/.zshrc:

```
function s6rc-reset {

    setopt local_options rm_star_silent no_rm_star_wait null_glob

    S6RC_WANTED="${XDG_STATE_HOME}/s6-rc/wanted"
    S6RC_COMPILED="${XDG_STATE_HOME}/s6-rc/compiled"
    S6RC_SCANDIR="${XDG_STATE_HOME}/s6-rc/scandir"
    S6RC_LIVE="${XDG_RUNTIME_DIR}/s6-rc"

    rm -f "${S6RC_WANTED}"/*
    rm -rf "${S6RC_COMPILED}"
    rm -f "${S6RC_SCANDIR}"/*
    rm -rf "${S6RC_LIVE}"*

}

function s6rc-live {

    # "${_at_}" expands each positional parameter as a separate
    argument.
    # Double quotes are required for this to happen.
    
    s6-rc -l "${XDG_RUNTIME_DIR}/s6-rc" "${_at_}"

}

function s6rc-svc {

    service=${argv[-1]}
    opts=${argv[1,-2]}

    s6-svc ${opts}
    "${XDG_RUNTIME_DIR}/s6-rc/servicedirs/${service}"

}
```

where `s6rc-svc` is the function i use to restart a service, bring
it down, etc.

Whew! That's obviously a lot; hope it's of some use. :-) i'm sure
there are various things that should be done differently, or that
could be improved, but i don't really want to get into the weeds
on this, given my limited personal resources.

Finally, earlier i wrote:

> This was part of my plan for a public repo of s6-rc services;
> i'll come back to this.

Something i've noticed is that many of us are constantly
re-inventing the wheel in terms of services. Yes, many of us
publicly share the services we've created, which might themselves
be based on similar services publicly shared by others. And yes,
it's true that a given service might require OS-specific
stuff. But my thought was that it might be nice to have something
like the package repos associated with various programming
languages, containing services that are designed to be
configurable as possible, so that they can be used 'out of the
box' by e.g. packagers, end-users, etc., without having to futz
with the details. Hence the `sh` / `user` directory structure i
described; i was thinking that such a 'service repo' could have a
directory structure something like:

/s6-services/execline/system
/s6-services/execline/user
/s6-services/sh/system
/s6-services/sh/user
/s6-rc-services/execline/system
/s6-rc-services/execline/user
/s6-rc-services/sh/system
/s6-rc-services/sh/user

and then possibly things like:

/s6-rc-services/python/system
/s6-rc-services/python/user

etc.

This would allow packages, end-users, etc. to make use of
whichever language is best-suited to their particular use-case,
without having to create bespoke services (even if they're based
on other bespoke services).

Of course, the release of s6-frontend changes the landscape. :-)
But i still feel the overall idea - of making it much easier for
packagers and users to get a working s6-based setup of some type -
is probably one that might be useful for people to consider.


Alexis.
Received on Mon Mar 02 2026 - 00:59:26 CET

This archive was generated by hypermail 2.4.0 : Mon Mar 02 2026 - 01:00:05 CET