Incus / LXD profile for GUI apps: Wayland, X11 and Pulseaudio

You will need to find out how does the polkit agent communicate with the processes, if it is not through a file on the filesystem. It’s through some live service, and it is highly likely it’s through D-Bus.

Seems that simply mounting the D-Bus socket from the host machine and sourcing DBUS_SESSION_BUS_ADDRESS to the proper location within the container (in my configuration, unix:path=/run/user/1000/bus) made it work flawlessly. Great!

1 Like

I updated the first post with a simplified profile for Ubuntu 24.04 as host.

Previous profiles are now here:

  • Preliminary profile for Ubuntu 24.04
  • Profile for Ubuntu 22.04 with kernel 6.5.0+
  • Profile for Ubuntu 22.04 with older kernels

4 posts were split to a new topic: Steam input devices

This gives the error and the container does not start.

lxc steam 20241015063508.841 ERROR    conf - ../src/lxc/conf.c:lxc_map_ids:3704 - newuidmap failed to write mapping "newuidmap: uid range [1000-1001) -> [1000-1001) not allowed": newuidmap 13508 0 1000000 1000 1000 1000 1 1001 1001001 999998999

Host is Ubuntu 24.04 with an Ubuntu 24.04 image.

Without the ID mapping, the container starts and it loads GUI apps. Is it required to have it?

In my testing, raw.idmap is required for Wayland socket to work on Ubuntu 24.04 host.

Do you get the same error when starting a new Ubuntu 24.04 container without GUI profile and adding raw.idmap by hand?

printf "uid $(id -u) 1000\ngid $(id -g) 1000" | incus config set <instance name> raw.idmap -

Edit:
In a clean Ubuntu 24.04 VM I can’t reproduce your error.

Both UID and GID are 1000.

$ incus profile show idmap
config:
  raw.idmap: |-
    uid 1000 1000
    gid 1000 1000
description: ""
devices: {}
name: idmap
used_by: []
$ incus launch images:alpine/edge mycontainer --profile default --profile idmap
Launching mycontainer
Error: Failed instance creation: Failed to run: /usr/libexec/incus/incusd forkstart mycontainer /var/lib/incus/containers /run/incus/mycontainer/lxc.conf: exit status 1
$ 

/etc/sub{gu}id contain

myusername:100000:65536
root:1000000:1000000000

I am getting this on a new system, and should be fairly vanilla.

Weird. My /etc/sub{gu}id are the same. Does this happen for you in a fresh Ubuntu 24.04 VM as well?

I reproduced with an Incus Ubuntu 24.04 VM, running Incus 6.0.0 (default packages).
Therefore, it should be reproducible by anyone.

Here is the error message again,

lxc mycontainer 20241017114318.361 ERROR    conf - ../src/lxc/conf.c:lxc_map_ids:3704 - newuidmap failed to write mapping "newuidmap: uid range [1000-1001) -> [1000-1001) not allowed": newuidmap 2893 0 1000000 1000 1000 1000 1 1001 1001001 999998999
lxc mycontainer 20241017114318.361 ERROR    start - ../src/lxc/start.c:lxc_spawn:1788 - Failed to set up id mapping.
lxc mycontainer 20241017114318.361 ERROR    lxccontainer - ../src/lxc/lxccontainer.c:wait_on_daemonized_start:878 - Received container state "ABORTING" instead of "RUNNING"
lxc mycontainer 20241017114318.362 ERROR    start - ../src/lxc/start.c:__lxc_start:2107 - Failed to spawn container "mycontainer"
lxc mycontainer 20241017114318.362 WARN     start - ../src/lxc/start.c:lxc_abort:1036 - No such process - Failed to send SIGKILL via pidfd 17 for process 2893
lxc 20241017114318.397 ERROR    af_unix - ../src/lxc/af_unix.c:lxc_abstract_unix_recv_fds_iov:218 - Connection reset by peer - Failed to receive response
lxc 20241017114318.397 ERROR    commands - ../src/lxc/commands.c:lxc_cmd_rsp_recv_fds:128 - Failed to receive file descriptors for command "get_init_pid"

There is some likelihood that some other binary is missing (uidmap is installed).
In any case, the issue is not related to running GUI apps but to the use of idmap in Incus.

@stgraber, can you please split up these posts about the idmap error in launching containers into a separate thread?

I confirm. The error occurs when Incus is installed from Ubuntu packages. When installed from Zabbly, everything works perfectly fine (both LTS and Stable).

@qkiel Thanks for putting the very useful instructions together. I tried your updated profile for running Ubuntu containers with Ubuntu 24.04 as host.

I recently moved to an openSUSE Tumbleweed host (I was using Kubuntu 24.04 before), but I still run Ubuntu containers from the standard Incus server image repository. Almost everything works (I successfully tested wayland, x11, camera, video, rendering, etc), except for the sound!

I used the instructions to the letter, but I couldn’t manage to get the sound in the container working. I tried many things that didn’t work (e.g. passing the pipewire/pulse devices as container/proxy, installing various packages and libraries, using other ubuntu versions (22.04 and 24.10)…).

Any ideas very much welcome!

------- FYI ------
My incus YAML profile:

name: wayland_new2
description: >-
Requires ‘incus_ct_gui.sh’ script. GUI Wayland and xWayland profile with
pipewire and pulseaudio, shifting enabled for all socket.
devices:
camera1:
busnum: ‘3’
devnum: ‘4’
gid: ‘1000’
productid: b756
type: usb
uid: ‘1000’
vendorid: 04f2
controlC0:
gid: ‘29’
source: /dev/snd/controlC0
type: unix-char
dri_card0:
gid: ‘44’
source: /dev/dri/card1
type: unix-char
dri_renderD128:
gid: ‘992’
source: /dev/dri/renderD128
type: unix-char
gpu:
gid: ‘44’
pci: ‘0000:00:02.0’
type: gpu
pipewire_manager_socket:
bind: container
connect: unix:/run/user/1000/pipewire-0-manager
gid: ‘1000’
listen: unix:/mnt/.container_sockets/pipewire-0-manager
mode: ‘0777’
security.gid: ‘1000’
security.uid: ‘1000’
type: proxy
uid: ‘1000’
pipewire_socket:
bind: container
connect: unix:/run/user/1000/pipewire-0
gid: ‘1000’
listen: unix:/mnt/.container_sockets/pipewire-0
mode: ‘0777’
security.gid: ‘1000’
security.uid: ‘1000’
type: proxy
uid: ‘1000’
pulseaudio_socket:
bind: container
connect: unix:/run/user/1000/pulse/native
gid: ‘1000’
listen: unix:/mnt/.container_sockets/native
mode: ‘0777’
security.gid: ‘1000’
security.uid: ‘1000’
type: proxy
uid: ‘1000’
video0:
gid: ‘44’
source: /dev/video0
type: unix-char
video1:
gid: ‘44’
source: /dev/video1
type: unix-char
video2:
gid: ‘44’
source: /dev/video2
type: unix-char
video3:
gid: ‘44’
source: /dev/video3
type: unix-char
wayland_socket:
path: /mnt/.container_sockets/wayland-0
shift: ‘true’
source: /run/user/1000/wayland-0
type: disk
xauthority_cookie:
path: /mnt/.container_sockets/.mutter-Xwaylandauth.copy
shift: ‘true’
source: /run/user/1000/.mutter-Xwaylandauth.incus
type: disk
xwayland_socket:
path: /mnt/.container_sockets/X1
shift: ‘true’
source: /tmp/.X11-unix/X1
type: disk
config:
security.nesting: ‘true’
raw.idmap: |-
uid 1000 1000
gid 1000 1000
project: default

The instance YAML configuration:

architecture: x86_64
config:
image.architecture: amd64
image.description: Ubuntu noble amd64 (20241230_07:42)
image.os: Ubuntu
image.release: noble
image.requirements.cgroup: v2
image.serial: ‘20241230_07:42’
image.type: squashfs
image.variant: default
volatile.base_image: 76128cb718e52dd32143c009bf15258ac14777884ddd666635e98b08f311054a
volatile.cloud-init.instance-id: 8fa97ee6-d6da-4736-8fdc-5ce2cd3f9a61
volatile.eth0.host_name: veth8227f039
volatile.eth0.hwaddr: 00:16:3e:d6:73:5f
volatile.eth0.name: eth0
volatile.idmap.base: ‘0’
volatile.idmap.current: >-
[{“Isuid”:true,“Isgid”:false,“Hostid”:400000000,“Nsid”:0,“Maprange”:1000},{“Isuid”:true,“Isgid”:false,“Hostid”:1000,“Nsid”:1000,“Maprange”:1},{“Isuid”:true,“Isgid”:false,“Hostid”:400001001,“Nsid”:1001,“Maprange”:499999000},{“Isuid”:false,“Isgid”:true,“Hostid”:400000000,“Nsid”:0,“Maprange”:1000},{“Isuid”:false,“Isgid”:true,“Hostid”:1000,“Nsid”:1000,“Maprange”:1},{“Isuid”:false,“Isgid”:true,“Hostid”:400001001,“Nsid”:1001,“Maprange”:499999000}]
volatile.idmap.next: >-
[{“Isuid”:true,“Isgid”:false,“Hostid”:400000000,“Nsid”:0,“Maprange”:1000},{“Isuid”:true,“Isgid”:false,“Hostid”:1000,“Nsid”:1000,“Maprange”:1},{“Isuid”:true,“Isgid”:false,“Hostid”:400001001,“Nsid”:1001,“Maprange”:499999000},{“Isuid”:false,“Isgid”:true,“Hostid”:400000000,“Nsid”:0,“Maprange”:1000},{“Isuid”:false,“Isgid”:true,“Hostid”:1000,“Nsid”:1000,“Maprange”:1},{“Isuid”:false,“Isgid”:true,“Hostid”:400001001,“Nsid”:1001,“Maprange”:499999000}]
volatile.last_state.idmap: ‘
volatile.last_state.power: RUNNING
volatile.last_state.ready: ‘false’
volatile.uuid: 093e5759-2234-4efa-91ca-d4cd6112d549
volatile.uuid.generation: 093e5759-2234-4efa-91ca-d4cd6112d549
devices: {}
ephemeral: false
profiles:

  • default
  • wayland_new
    stateful: false
    description: ubuntu 24.04
    created_at: ‘2025-01-02T23:42:10.186448033Z’
    name: ubuntu
    status: Running
    status_code: 103
    last_used_at: ‘2025-01-02T23:53:56.15397395Z’
    location: none
    type: container
    project: default

From the container:

ubuntu@ubuntu:~$ ll /tmp/.X11-unix/X?
ll /run/user/*/
ll /run/user/*/pulse/
lrwxrwxrwx 1 ubuntu ubuntu 26 Jan 2 23:54 /tmp/.X11-unix/X1 → /mnt/.container_sockets/X1=
total 4
drwx------ 6 ubuntu ubuntu 280 Jan 2 23:54 ./
drwxr-xr-x 3 root root 60 Jan 2 23:54 …/
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 bus=
drwx------ 3 ubuntu ubuntu 60 Jan 2 23:54 dbus-1/
drwx------ 2 ubuntu ubuntu 160 Jan 2 23:54 gnupg/
-rw------- 1 ubuntu ubuntu 94 Jan 2 23:54 .mutter-Xwaylandauth.copy
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0=
-rw-rw---- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0.lock
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0-manager=
-rw-rw---- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0-manager.lock
drwxr-xr-x 2 ubuntu ubuntu 80 Jan 2 23:54 pulse/
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 snapd-session-agent.socket=
drwxr-xr-x 6 ubuntu ubuntu 160 Jan 2 23:54 systemd/
lrwxrwxrwx 1 ubuntu ubuntu 33 Jan 2 23:54 wayland-0 → /mnt/.container_sockets/wayland-0=
total 4
drwxr-xr-x 2 ubuntu ubuntu 80 Jan 2 23:54 ./
drwx------ 6 ubuntu ubuntu 280 Jan 2 23:54 …/
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 native=
-rw-rw-r-- 1 ubuntu ubuntu 4 Jan 2 23:54 pid

ubuntu@ubuntu:~$ systemctl --user status pipewire pipewire-pulse wireplumber
● pipewire.service - PipeWire Multimedia Service
Loaded: loaded (/usr/lib/systemd/user/pipewire.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-01-02 23:54:01 UTC; 5min ago
TriggeredBy: ● pipewire.socket
Main PID: 449 (pipewire)
Tasks: 3 (limit: 18686)
Memory: 3.4M (peak: 4.1M)
CPU: 225ms
CGroup: /user.slice/user-1000.slice/user@1000.service/session.slice/pipewire.service
└─449 /usr/bin/pipewire

Jan 02 23:54:01 ubuntu systemd[440]: Started pipewire.service - PipeWire Multimedia Service.
Jan 02 23:54:01 ubuntu pipewire[449]: mod.jackdbus-detect: Failed to receive jackdbus reply: org.freedesktop.DBus.Error.ServiceUnknown: The name org.jackaudio.service was not provided by any .service files

● pipewire-pulse.service - PipeWire PulseAudio
Loaded: loaded (/usr/lib/systemd/user/pipewire-pulse.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-01-02 23:54:01 UTC; 5min ago
TriggeredBy: ● pipewire-pulse.socket
Main PID: 453 (pipewire-pulse)
Tasks: 3 (limit: 18686)
Memory: 6.9M (peak: 7.8M)
CPU: 328ms
CGroup: /user.slice/user-1000.slice/user@1000.service/session.slice/pipewire-pulse.service
└─453 /usr/bin/pipewire-pulse

Jan 02 23:54:01 ubuntu systemd[440]: Started pipewire-pulse.service - PipeWire PulseAudio.
Jan 02 23:54:56 ubuntu pipewire-pulse[453]: default: snap_get_audio_permissions: kernel lacks ‘fine grained unix mediation’; snap audio permissions won’t be honored.
Jan 02 23:54:56 ubuntu pipewire-pulse[453]: default: snap_get_audio_permissions: kernel lacks ‘fine grained unix mediation’; snap audio permissions won’t be honored.
Jan 02 23:55:13 ubuntu pipewire-pulse[453]: default: snap_get_audio_permissions: kernel lacks ‘fine grained unix mediation’; snap audio permissions won’t be honored.

● wireplumber.service - Multimedia Service Session Manager
Loaded: loaded (/usr/lib/systemd/user/wireplumber.service; enabled; preset: enabled)
Active: active (running) since Thu 2025-01-02 23:54:01 UTC; 5min ago
Main PID: 451 (wireplumber)
Tasks: 6 (limit: 18686)
Memory: 3.4M (peak: 3.9M)
CPU: 40ms
CGroup: /user.slice/user-1000.slice/user@1000.service/session.slice/wireplumber.service
└─451 /usr/bin/wireplumber

Jan 02 23:54:01 ubuntu systemd[440]: Started wireplumber.service - Multimedia Service Session Manager.
Jan 02 23:54:01 ubuntu wireplumber[451]: SPA handle ‘api.libcamera.enum.manager’ could not be loaded; is it installed?
Jan 02 23:54:01 ubuntu wireplumber[451]: PipeWire’s libcamera SPA missing or broken. libcamera not supported.
Jan 02 23:54:01 ubuntu wireplumber[451]: SPA handle ‘api.bluez5.enum.dbus’ could not be loaded; is it installed?
Jan 02 23:54:01 ubuntu wireplumber[451]: PipeWire’s BlueZ SPA missing or broken. Bluetooth not supported.
Jan 02 23:54:01 ubuntu wireplumber[451]: WpPortalPermissionStorePlugin:0x55c3f2194e10 Failed to call Lookup: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.impl.portal.PermissionSt>
Jan 02 23:54:01 ubuntu wireplumber[451]: WpPortalPermissionStorePlugin:0x55c3f2194e10 Failed to call Lookup: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.impl.portal.Permissi

pactl info
Server String: /run/user/1000/pulse/native
Library Protocol Version: 35
Server Protocol Version: 35
Is Local: yes
Client Index: 64
Tile Size: 65472
User Name: ubuntu
Host Name: ubuntu
Server Name: PulseAudio (on PipeWire 1.0.5)
Server Version: 15.0.0
Default Sample Specification: float32le 2ch 48000Hz
Default Channel Map: front-left,front-right
Default Sink: auto_null
Default Source: auto_null.monitor
Cookie: 8b93:070f

from my user’s .profile
[[ ! -d “/run/user/1000/pulse” ]] && mkdir -m 700 “/run/user/1000/pulse”
[[ -S “/mnt/.container_sockets/native” && -d “/run/user/1000/pulse” && ! -e “/run/user/1000/pulse/native” ]] && ln -s “/mnt/.container_sockets/native” “/run/user/1000/pulse/native”
[[ -S “/mnt/.container_sockets/pipewire-0” && ! -e “/run/user/1000/pipewire-0” ]] && ln -s “/mnt/.container_sockets/pipewire-0” “/run/user/1000/pipewire-0”
[[ -S “/mnt/.container_sockets/pipewire-0-manager” && ! -e “/run/user/1000/pipewire-0-manager” ]] && ln -s “/mnt/.container_sockets/pipewire-0-manager” “/run/user/1000/pipewire-0-manager”
[[ -S “/mnt/.container_sockets/wayland-0” && ! -e “/run/user/1000/wayland-0” ]] && ln -s “/mnt/.container_sockets/wayland-0” “/run/user/1000/wayland-0”
[[ -S “/mnt/.container_sockets/X1” && ! -e “/tmp/.X11-unix/X1” ]] && ln -s “/mnt/.container_sockets/X1” “/tmp/.X11-unix/X1”
[[ -f “/mnt/.container_sockets/.mutter-Xwaylandauth.copy” && ! -e “/run/user/1000/.mutter-Xwaylandauth.copy” ]] && cp “/mnt/.container_sockets/.mutter-Xwaylandauth.copy” “/run/user/1000/.mutter-Xwaylandauth.copy”
export WAYLAND_DISPLAY=wayland-0
export XDG_SESSION_TYPE=wayland
export QT_QPA_PLATFORM=wayland
export DISPLAY=:1
export XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.copy
export NO_AT_BRIDGE=1
export QT_QPA_PLATFORM=wayland
export QT_QPA_PLATFORMTHEME=qt5ct
export CLUTTER_BACKEND=wayland
export SDL_VIDEODRIVER=wayland
export GDK_BACKEND=wayland
export WINIT_UNIX_BACKEND=wayland
export XIM=ibus
export XIM_PROGRAM=/usr/bin/ibus
export QT_IM_MODULE=ibus
export GTK_IM_MODULE=ibus
export XMODIFIERS=ibus
export DefaultIMModule=ibus
export PULSE_SERVER=/run/user/1000/pulse/native
export PIPEWIRE_REMOTE=/run/user/1000/pipewire-0-manager
ibus-daemon -drx

My Tumbleweed host:

Operating System: openSUSE Tumbleweed 20241226
KDE Plasma Version: 6.2.4
KDE Frameworks Version: 6.9.0
Qt Version: 6.8.1
Kernel Version: 6.12.6-1-default (64-bit)
Graphics Platform: Wayland
Processors: 20 × 12th Gen Intel® Core™ i7-12700H
Memory: 16,5 GB of RAM
Graphics Processor: Mesa Intel® Iris® Xe Graphics
Manufacturer: LENOVO
Product Name: 82UT
System Version: Yoga Slim 7 Pro 14IAH7

When I run ll /run/user/*/pipe* inside a container, I do get this:

lrwxrwxrwx 1 ubuntu ubuntu 34 sty  3 09:49 /run/user/1000/pipewire-0 -> /mnt/.container_sockets/pipewire-0=
lrwxrwxrwx 1 ubuntu ubuntu 42 sty  3 09:49 /run/user/1000/pipewire-0-manager -> /mnt/.container_sockets/pipewire-0-manager=

Notice that pipewire sockets are links to the /mnt/.container_sockets/ folder. But in your output, we see regular sockets srw-rw-rw- instead of links lrwxrwxrwx:

srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0=
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 pipewire-0-manager=
srw-rw-rw- 1 ubuntu ubuntu 0 Jan 2 23:54 native=

It seems that something is creating those sockets and preventing linking from /mnt/.container_sockets/ folder. Did you install something related to pipewire / pulse in a constainer beyond pulseaudio-utils package?

When I run systemctl --user status pipewire pipewire-pulse wireplumber in a container, I do get:

Unit pipewire.service could not be found.
Unit pipewire-pulse.service could not be found.
Unit wireplumber.service could not be found.

Thanks a ton for the swift and effective reply! The sound actually works now!

The problem was indeed me re-installing pipewire and wireplumber in the container (in an attempt to fix issues), that ruined those links/sockets. Now that I didn’t install them, your script works as intended!

Again thanks a lot! I also confirm it worked for an oracular 24.10 container…

:love_you_gesture:

Hey. Mounting the dbus socket onto the containers was enough for basic render stuff, but trying to interact/applications trying to come at desktop stuff still fails for no interface/object of XDG from the host machine is present at the container at all. How would you guys recommend provide/populate of the host’s machine XDG stuff onto the containers?

Can you explain what exactly are you trying to do, what doesn’t work as expected, and what container you’re using?

I’m running Noble Ubuntu Images on an Arch Linux host that runs Hyprland as it’s compositor.

What I’m trying to achieve is the generic goal of this same thread: have my applications be containerized from the totality of the system and from one another, only sharing the sockets/APIs necessary for my graphical backend/desktop environment.

What doesn’t work is any application-specific procedure which would fallback to XDG/FreeDesktop stuff.

  • Launching Firefox itself would throw logs that XDG services couldn’t be located, or that certain settings of the FreeDesktop which are proper to the host’s graphical environment couldn’t be accessed.
  • Trying to access a file-picker on an application won’t work.
  • Applications aren’t styled according to the host’s XDG-defined settings

Do note that I don’t think this is a concern of Hyprland on specific, as other users (Incus / LXD profile for GUI apps: Wayland, X11 and Pulseaudio - #31 by nnbyte for example), have shown application logs where there are issues with XDG queries/usages.

How do you install Firefox inside container? As a snap or from Mozilla PPA? Show me the exact error you’re seeing and I’ll try to reproduce it. Let’s focus on one app at a time.

This is a script I run in every Ubuntu container after it starts (just once, not every boot):

incus_ct_gui.sh
#!/bin/bash
#
# This script should be run inside Incus containers. It links sockets added by the 'gui' profile, from ${mnt_dir} to their proper locations on every login, installs a couple of packages and sets up necessary environment variables.

readonly mnt_dir="/mnt/.container_sockets"
readonly run_dir="$XDG_RUNTIME_DIR"
readonly tmp_dir="/tmp/.X11-unix"

function modify_profile() {
  # Add socket linking commands to the "$HOME/.profile" file, copy Xwaylandauth cookie and set up necessary environment variables.
  # Now on every user login sockets from ${mnt_dir} will be linked to their proper locations.
  cat << EOF >> "$HOME/.profile"
[[ ! -d "${run_dir}/pulse" ]] && mkdir -m 700 "${run_dir}/pulse"
[[ -S "${mnt_dir}/native" && -d "${run_dir}/pulse" && ! -e "${run_dir}/pulse/native" ]] && ln -s "${mnt_dir}/native" "${run_dir}/pulse/native"
[[ -S "${mnt_dir}/pipewire-0" && ! -e "${run_dir}/pipewire-0" ]] && ln -s "${mnt_dir}/pipewire-0" "${run_dir}/pipewire-0"
[[ -S "${mnt_dir}/pipewire-0-manager" && ! -e "${run_dir}/pipewire-0-manager" ]] && ln -s "${mnt_dir}/pipewire-0-manager" "${run_dir}/pipewire-0-manager"
[[ -S "${mnt_dir}/wayland-0" && ! -e "${run_dir}/wayland-0" ]] && ln -s "${mnt_dir}/wayland-0" "${run_dir}/wayland-0"
[[ -S "${mnt_dir}/X0" && ! -e "${tmp_dir}/X0" ]] && ln -s "${mnt_dir}/X0" "${tmp_dir}/X0"
[[ -S "${mnt_dir}/X1" && ! -e "${tmp_dir}/X1" ]] && ln -s "${mnt_dir}/X1" "${tmp_dir}/X1"
[[ -f "${mnt_dir}/.mutter-Xwaylandauth.copy" && ! -e "${run_dir}/.mutter-Xwaylandauth.copy" ]] && cp "${mnt_dir}/.mutter-Xwaylandauth.copy" "${run_dir}/.mutter-Xwaylandauth.copy"
export WAYLAND_DISPLAY=wayland-0
export XDG_SESSION_TYPE=wayland
export QT_QPA_PLATFORM=wayland
export DISPLAY=:1
export XAUTHORITY=${run_dir}/.mutter-Xwaylandauth.copy
export GTK_THEME=Yaru:dark
EOF
}

function modify_gsettings() {
  gsettings set org.gnome.desktop.sound event-sounds "false"
  gsettings set org.gnome.desktop.interface icon-theme "Yaru"
  gsettings set org.gnome.desktop.interface cursor-theme "Yaru"
  gsettings set org.gnome.desktop.interface gtk-theme "Yaru-dark"
  gsettings set org.gnome.desktop.interface color-scheme "prefer-dark"
}

function main() {
  # Add user to the video and render groups.
  sudo usermod -a -G video,render "$LOGNAME"
  # libglib2.0-bin is for gsettings
  # xsettingsd provides settings to X11 applications ???
  sudo apt update && sudo apt upgrade -y && sudo apt install -y pulseaudio-utils dbus-user-session nano bash-completion language-pack-en apparmor libglib2.0-bin xsettingsd gsettings-desktop-schemas yaru-theme-gtk yaru-theme-icon fonts-noto-core fonts-noto-mono fonts-noto-color-emoji
  modify_profile
  modify_gsettings
}

main

Does that help? I don’t pass any XDG stuff into container. I set them up inside as needed.

When I tried to install Firefox using official .deb, I had to install those additional packages inside container:

sudo apt install libpci3 libgl1-mesa-dri mesa-utils

And add MOZ_ENABLE_WAYLAND=1 to my .profile file inside container:

echo "export MOZ_ENABLE_WAYLAND=1" >> .profile

When I can I will share the profile that I pieced together for a Debian 12 host and an Ubuntu 22.04 container running Steam.

Thank you @qkiel for the direction and info. And much thanks to @simos for the info, here and on your blog, about. You all rock. :+1: