Flatpak, DBus and Friends on KISS Linux

Last updated:

Why Flatpak?

While I prefer libre, lean, portable software, not everything I need is part of this group. Some software is very complex, tightly coupled and annoying to build, like Telegram Desktop, LibreOffice and Firefox, or even proprietary and linked to some very specific libraries (e.g. glibc), like Steam.

Flatpak runs small, sandboxed, containers that put each application in its ideal environment, without blasting my system into space.

As of writing, Flatpak is packaged in community as flatpak but DBus and some special daemons are needed in order to poke most holes in the sandbox.

DBus

DBus is an IPC system used by various userspace daemons.

Installation and Usage

To get DBus, install the dbus package from the kiss-dbus repo. Note that some tools might need recompilation or additional build settings to enable their respective DBus support.

To start a DBus session, wrap your compositor's start command into dbus-run-session. Thus, for example, if you use sway you could start it like this in your .profile:

dbus-run-session sway

Personally I also run PipeWire through an inline shell script so that it terminates alongside the DBus session:

dbus-run-session sh -c 'pipewire & pipewire-pulse & /usr/bin/sway'

Activation Environment

The DBus daemon needs explicit access to certain environment variables so that it can hand them over to certain bus-spawned processes like Flatpak.

To pass them, call dbus-update-activation-environment followed by the list of env vars you want to pass to the daemon. You can also pass variables "on the fly" using the NAME=value syntax. Since most of the variables required are provided by the desktop environment, you must run this command under it.

The specific variables will depend on the software you're running, but in general the essentials are:

DISPLAY and WAYLAND_DISPLAY will be already provided by your display environment, depending on availability (i.e. pure Wayland installs won't have DISPLAY).

XDG_CURRENT_DESKTOP might have to be manually set: it should contain the name of your desktop enviroment, by convention in lowercase (e.g. sway). The content of this variable will be used by various software for applying environment-specific settings (e.g. something for sway, something else for KDE).

In my case I put export XDG_CURRENT_DESKTOP=sway in my .profile right before running sway so that it can be inherited around.

XCURSOR_SIZE and XCURSOR_THEME, if available, may be passed too, as some clients depend on it to style the cursor.

This is the command I put in my sway configuration:

exec dbus-update-activation-environment WAYLAND_DISPLAY DISPLAY XDG_CURRENT_DESKTOP SWAYSOCK I3SOCK XCURSOR_SIZE XCURSOR_THEME

Note that I3SOCK and SWAYSOCK are specific to sway. I'm not aware of how exactly and if these variables are used but sway's documentation recommends that. When in doubt, refer to the documentation of your specific desktop environment if possible.

XDG Portals

XDG Portals are DBus wrappers for various system APIs, allowing sandboxed applications to safely access specific systems. Flatpak's sandboxing system decides which API is visible to each application through a permission system.

You can mix and match implementations for each interface, through a configuration file that spawns the correct daemon when in need.

Installation

Both xdg-desktop-portal and xdg-desktop-portal-wlr are available from the kiss-dbus repo. Other daemons will require external packages.

Running

The only daemon you have to run is/usr/lib/xdg-desktop-portal, which will read the preferences for each desktop environment and orchestrate everything as described above.

xdg-desktop-portal is a "session daemon" and as such has to be instanced inside of a DBus session.

In my case I added this line to my sway configuration:

exec /usr/lib/xdg-desktop-portal -r

The -r switch makes it replace the current instance, if any.

Configuration

The configuration file is present in $XDG_CONFIG_HOME/xdg-desktop-portal/$XDG_CURRENT_DESKTOP-portals.conf.

Taking sway for example, a common setup is to have xdg-desktop-portal-gtk as the default provider (for all desktop enviroment agnostic integrations), with two wlroots-specific interfaces taken from xdg-desktop-portal-wlr (for screen sharing):

[preferred]
default=gtk
org.freedesktop.impl.portal.Screenshot=wlr
org.freedesktop.impl.portal.ScreenCast=wlr

Note that screen sharing through portals requires PipeWire.

Tips and Tricks

XDG Document Portal does not work

Some stuff, namely xdg-document-portal (included with xdg-desktop-portal if not patched out), seems to break when XDG_RUNTIME_DIR points to a different directory than the standard /run/user/$(id -u). So, well... Make sure that it's set to that. setup-run.boot from the goodies repo can help setting it up.

Bubblewrap set-uid and Permmissions

For some reason, bubblewrap (/usr/bin/bwrap) in suid mode has issues with its permissions for xdg-document-portal, which is essential for isolated file dialogs. A quick workaround is to make a bubblewrap group and assign it to both your user and the bwrap binary:

addgroup $USER bubblewrap
chgrp bubblewrap /usr/bin/bwrap

PipeWire only reports a single "Dummy Output" card when under a DBus session

PipeWire gets plenty confused when it finds a DBus connection, as it tries to interact with a certain "device reservation" API. I have no idea what daemon is supposed to answer to that but it looks like it's not needed in our case, so it's easier to just get rid of it.

To disable it, simply add a configuration file in a valid wireplumber configuration directory, like $XDG_CONFIG_HOME/wireplumber, containing the following snippet:

wireplumber.profiles = {
  main = {
    support.reserve-device = disabled
  }
}

Without this tweak it will try in vain to reserve any audio device. In the end you won't have a single device available because it thinks they're all taken.