Wayland Plasma DE in non-privileged mode

Hello, my plan was to build a container which contains an Archlinux system to run a full wayland plasma desktop environment (DE).

I’ve been able to run a fully working instance thanks to the configuration detailed below AND the use of the ‘security.privileged=true’ mode starting the plasma session directly from TTY2.
My problem is that I don’t want to leave the ‘security.privileged=true’ mode always activated to replace it by the only permissions needed.

To achieve this, I’ve been trying to reproduce the ‘privileged’ mode with a dedicated profile(see below) to then reduce it to the strict minimum but every of my (numerous) attempts failed like this:

user@PLASMA>startplasma-wayland
startplasma-wayland: Shutting down...
startplasmacompositor: Shutting down...
startplasmacompositor: Done.

With the ‘journalctl’ error:

user@PLASMA>journalctl -b0 | grep "kwin_wayland\|systemd-logind"
PLASMA kwin_wayland[497]: No backend specified, automatically choosing drm
PLASMA systemd-logind[402]: Cannot set K_OFF on /dev/tty2: Operation not permitted
PLASMA systemd-logind[402]: Failed to restore VT, ignoring: Operation not permitted
PLASMA kwin_wayland[497]: kwin_core: Failed to take control of /org/freedesktop/login1/session/c1 session. Maybe another compositor is running?
PLASMA kwin_wayland[497]: kwin_wayland_drm: failed to open drm device at "/dev/dri/card2"
PLASMA kwin_wayland[497]: kwin_wayland_drm: failed to open drm device at "/dev/dri/card1"
PLASMA kwin_wayland[497]: kwin_wayland_drm: No suitable DRM devices have been found

Here is the profile used attempting to simulate the ‘privileged’ option:

>incus profile show dbg
config:
  raw.lxc: |
    lxc.mount.auto=proc sys cgroup
    lxc.apparmor.profile=unconfined
    lxc.cap.keep = chown dac_override fsetid fowner mknod net_raw setgid setuid setfcap setpcap mac_admin net_admin net_bind_service sys_admin sys_chroot kill audit_control audit_read audit_write syslog bpf dac_read_search ipc_lock ipc_owner linux_immutable mac_admin mac_override net_broadcast sys_nice sys_pacct sys_resource sys_time sys_tty_config sys_ptrace sys_boot lease wake_alarm block_suspend perfmon
  security.nesting: "true"
  security.syscalls.intercept.bpf: "true"
  security.syscalls.intercept.bpf.devices: "true"
  security.syscalls.intercept.mount: "true"
  security.syscalls.intercept.mount.shift: "true"
  security.syscalls.intercept.setxattr: "true"
description: ""
devices:
  dev-kfd:
    gid: "989"
    mode: "0666"
    path: /dev/kfd
    required: "false"
    type: unix-char
name: dbg
used_by:
- /1.0/instances/plasma
project: default

The configuration of the container is:

>incus config show -e
architecture: x86_64
config:
  boot.autostart: "false"
  environment.PULSE_COOKIE: /tmp/pulseaudio.cookie
  environment.PULSE_SERVER: unix:/home/user/.tmp/pulseaudio.socket
  image.architecture: x86_64
  image.description: arc-rdgvpa + plasma & utilities for desktop use
  image.name: archlinux-x86_64
  image.os: archlinux
  image.release: arc-plasma-256
  image.serial: "20250926_2031"
  image.variant: default
  linux.kernel_modules: amdgpu,fuse
  raw.idmap: both 0-65536 0-65536
  raw.lxc: lxc.apparmor.profile=unconfined
  security.nesting: "true"
  security.syscalls.intercept.bpf: "true"
  security.syscalls.intercept.bpf.devices: "true"
  security.syscalls.intercept.mount: "true"
  security.syscalls.intercept.mount.shift: "true"
  security.syscalls.intercept.setxattr: "true"
  volatile.base_image: 3de8f062179f9c6264a051b0caf2919ba0ceb663015b87fddc911c564da94760
  volatile.cloud-init.instance-id: bb8e75c2-07a3-4897-aa35-fe5a8afe4d7a
  volatile.eth0.host_name: veth60f4ed54
  volatile.eth0.hwaddr: 10:66:6a:ed:bc:81
  volatile.idmap.base: "0"
  volatile.idmap.current: '[{"Isuid":true,"Isgid":true,"Hostid":0,"Nsid":0,"Maprange":65537}]'
  volatile.idmap.next: '[{"Isuid":true,"Isgid":true,"Hostid":0,"Nsid":0,"Maprange":65537}]'
  volatile.last_state.idmap: '[]'
  volatile.last_state.power: RUNNING
  volatile.uuid: aa4914a8-f71a-4e26-b27e-1f2a739c2e48
  volatile.uuid.generation: aa4914a8-f71a-4e26-b27e-1f2a739c2e48
devices:
  dev-dri-rd128:
    gid: "989"
    major: "226"
    minor: "128"
    mode: "0666"
    path: /dev/dri/renderD128
    type: unix-char
    uid: "0"
  dev-dri-rd129:
    gid: "989"
    major: "226"
    minor: "129"
    mode: "0666"
    path: /dev/dri/renderD129
    type: unix-char
    uid: "0"
  dev-input-evt0:
    gid: "994"
    mode: "0666"
    path: /dev/input/event0
    required: "false"
    type: unix-char
  dev-input-evt1:
    gid: "994"
    mode: "0666"
    path: /dev/input/event1
    required: "false"
    type: unix-char
  dev-input-evt2:
    gid: "994"
    mode: "0666"
    path: /dev/input/event2
    required: "false"
    type: unix-char
  dev-input-js0:
    gid: "994"
    mode: "0666"
    path: /dev/input/js0
    required: "false"
    type: unix-char
  dev-input-mice:
    gid: "994"
    mode: "0666"
    path: /dev/input/mice
    required: "false"
    type: unix-char
  dev-input-mouse0:
    gid: "994"
    mode: "0666"
    path: /dev/input/mouse0
    required: "false"
    type: unix-char
  dev-input-mouse1:
    gid: "994"
    mode: "0666"
    path: /dev/input/mouse0
    required: "false"
    type: unix-char
  dev-kfd:
    gid: "989"
    mode: "0666"
    path: /dev/kfd
    required: "false"
    type: unix-char
  dri_card1:
    gid: "985"
    major: "226"
    minor: "1"
    mode: "0660"
    path: /dev/dri/card1
    type: unix-char
    uid: "0"
  dri_card2:
    gid: "985"
    major: "226"
    minor: "2"
    mode: "0660"
    path: /dev/dri/card2
    type: unix-char
    uid: "0"
  eth0:
    name: eth0
    network: incusbr0
    type: nic
  host:
    path: /host
    recursive: "true"
    source: /guest/plasma
    type: disk
  pasocket:
    path: /home/user/.tmp/pulseaudio.socket
    source: /run/user/1000/pulse/native
    type: disk
  root:
    path: /
    pool: main
    type: disk
  tty:
    gid: "5"
    mode: "0620"
    path: /dev/tty
    source: /dev/tty
    type: unix-char
  tty2:
    gid: "5"
    mode: "0620"
    path: /dev/tty2
    source: /dev/tty2
    type: unix-char
  tty7:
    gid: "5"
    mode: "0620"
    path: /dev/tty7
    source: /dev/tty7
    type: unix-char
  udev:
    path: /run/udev/data
    source: /run/udev/data
    type: disk
ephemeral: false
profiles:
- default
- dbg
- run-udev-data
stateful: false
description: ""

(please note that ‘/run/udev/data’ profile is mounted after the start of the instance since it’s located in a ramfs mount)

The container’s log is empty:

>incus info plasma --show-log
Name: plasma
Description:
Status: RUNNING
Type: container
Architecture: x86_64
PID: 1547
Created: 2025/10/15 13:28 CEST
Last Used: 2025/10/15 13:28 CEST
Started: 2025/10/15 13:28 CEST

Resources:
  Processes: 30
  CPU usage:
    CPU usage (in seconds): 3
  Memory usage:
    Memory (current): 1.02GiB
  Network usage:
    eth0:
      Type: broadcast
      State: UP
      Host interface: veth4442a63d
      MAC address: 10:66:6a:4c:4c:cf
      MTU: 1500
      Bytes received: 15.88kB
      Bytes sent: 14.94kB
      Packets received: 86
      Packets sent: 113
      IP addresses:
        inet:  10.177.1.93/24 (global)
        inet6: fe80::1266:6aff:fe4c:4ccf/64 (link)
    lo:
      Type: loopback
      State: UP
      MTU: 65536
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0
      IP addresses:
        inet:  127.0.0.1/8 (local)
        inet6: ::1/128 (local)

Log:

%s

Additionally, the environment once the user session is started and when ‘startplasma_wayland’ is issued is:

user@plasma>env|sort
container=lxc
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
DEBUGINFOD_URLS=https://debuginfod.archlinux.org
EDITOR=/usr/bin/nano
HOME=/home/user
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LOGNAME=user
MAIL=/var/spool/mail/user
MOTD_SHOWN=pam
OLDPWD=/home/user
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
PULSE_COOKIE=/tmp/pulseaudio.cookie
PULSE_SERVER=unix:/home/user/.tmp/pulseaudio.socket
PWD=/host
SHELL=/usr/bin/bash
SHLVL=2
SUDO_EDITOR=/usr/bin/nano
TERM=linux
USER=user
_=/usr/bin/env
XDG_DATA_DIRS=/home/user/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
XDG_RUNTIME_DIR=/run/user/1000
XDG_SEAT=seat0
XDG_SESSION_CLASS=user
XDG_SESSION_ID=c1
XDG_SESSION_TYPE=tty
XDG_VTNR=2

Finally, the host hw/sw version:

OS: Arch Linux x86_64
Host: ASUS TUF Gaming A16 FA617NS_FA617NS 1.0
Kernel: 6.14.10-arch1-1
Packages: 1275 (pacman)
Shell: bash 5.2.37
CPU: AMD Ryzen 7 7735HS with Radeon Graphics (16) @ 4.830GHz
GPU: AMD ATI Radeon 680M
GPU: AMD ATI Radeon RX 7600/7600 XT/7600M XT/7600S/7700S / PRO W7600
Memory: 801MiB / 15219MiB
>pacman -Q | grep 'incus\|lxc'
incus 6.13.0-1
lxc 1:6.0.4-2
lxcfs 6.0.4-1

And the container packages:

>lxc exec plasma -- su - user -c "pacman -Q" | grep 'plasma\|wayland'
egl-wayland 4:1.1.19-1
kdeplasma-addons 6.3.5-1
kwayland 6.3.5-1
kwayland-integration 6.3.5-1
kwayland5 5.116.0-1
lib32-wayland 1.23.1-1
libplasma 6.3.5-1
plasma-activities 6.3.5-1
plasma-activities-stats 6.3.5-1
plasma-browser-integration 6.3.5-1
plasma-desktop 6.3.5-1
plasma-integration 6.3.5-2
plasma-nm 6.3.5-1
plasma-workspace 6.3.5-2
plasma5support 6.3.5-2
qt5-wayland 5.15.17+kde+r57-1
qt6-wayland 6.9.1-1
wayland 1.23.1-2
xorg-xwayland 24.1.6-1
xwayland-satellite 0.5.1-1

Using a ‘gpu’ type instead of the ‘/dev/dri’ unix-char device doesn’t work either.
I’ve also tried various ‘udevadm trigger’, ‘systemctl restart systemd-login.service’ commands from inside the container but it ended with no results.

After days of trying to solve around this ‘unprivileged’ issue, my main question will be:
Is reproducing the ‘privileged’ mode something that can be achieved using a configuration/profile?
If yes, can someone provide a reference for this ‘privileged’ profile (or a document which summarizes what this mode exactly do)?

Moreover, if somebody sees an error or has any hint on how to run this wayland DE container in ‘unprivileged’ mode, he will be my hero :slight_smile:

Welcome!

I think that some of the packages have not been tested yet for use in a container environment, therefore they crash instead of handling the issue in a better way.

If that is the case, it would require debugging the debug packages to figure out what causes the crash, then figure out a patch to avoid the crash.

A couple of years ago there was such a post here exactly on that, but for X11.

If Wayland does not have a hard requirement that a container cannot fulfill, then Wayland should eventually work in a container.