Re: First time user experiences

Alexis <[email protected]> Mon, 02 Mar 2026 10:59:26 +1100
Newsgroups gmane.comp.sysutils.supervision.general
Message-ID <[email protected]>
Guillermo <[email protected]> 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 {

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

}

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.