Skip to content

selkies-kde-desktop

Recipe card from the charly-selkies plugin (Images — the deployable catalog).

selkies-kde-desktop — KDE Plasma selkies streaming flavor

Section titled “selkies-kde-desktop — KDE Plasma selkies streaming flavor”

selkies-kde-desktop is the KDE Plasma flavor of the selkies streaming desktop, the sibling of the labwc flavor (selkies-desktop). Both share one transport core and differ ONLY in the nested compositor (R3 — no duplicated streaming stack).

Three-tier decomposition (shared with the labwc flavor)

Section titled “Three-tier decomposition (shared with the labwc flavor)”
  • selkies-core — the compositor-agnostic streaming spine: the selkies transport (pixelflux owns wayland-1 + capture-server + traefik:3000 + ffmpeg + pipewire) plus the shared fixings (chrome, chrome-cdp, desktop-fonts, wl-tools, wl-screenshot/record/overlay-pixelflux, a11y-tools, xterm, tmux, asciinema, fastfetch, sshd). NO compositor, NO panel/notifier.
  • kde-selkies — the KDE nested-compositor PRIMITIVE (the swappable seam, analogous to labwc): require: [selkies, kde-shell, pipewire, dbus]; a single supervisord service (kde-selkies-session, priority 12, scope: user) that polls for /tmp/wayland-1 then launches kwin_wayland --wayland-display wayland-1 DIRECTLY (nested) + plasmashell on kwin’s wayland-0 — see the De-SDDM section for why NOT startplasma-wayland.
  • kde-shell — the SDDM-free Plasma SESSION package leaf (plasma-desktop deps-puller + kwin_wayland + plasmashell + the core session components + curated apps), shared by kde-desktop (bare-metal SDDM seat) and kde-selkies (headless pod). Workstation-only extras (kdeconnect, bluedevil, partition tools, kwallet, …) stay in kde-desktop so the streaming pod stays lean.
  • selkies-kde-desktop (this metalayer) = selkies-core + kde-selkies (which pulls kde-shell transitively). KDE ships its own audio applet (plasma-pa) + panel + notifier, so there is NO waybar/swaync/pavucontrol here.

De-SDDM: how Plasma runs headless as a pod (the load-bearing design)

Section titled “De-SDDM: how Plasma runs headless as a pod (the load-bearing design)”

A pod has no DRM seat, no SDDM, no graphical.target. kde-selkies therefore launches kwin_wayland --wayland-display wayland-1 DIRECTLY under a supervisord poll-for-wayland-1 service — NOT startplasma-wayland, no display manager, no after: graphical-session.target. The explicit --wayland-display wayland-1 flag is LOAD-BEARING: it makes KWin NEST into pixelflux (present its composited output as a wayland-1 client surface pixelflux captures) and create wayland-0 for Plasma’s own clients (plasmashell, Chrome) — the KDE analogue of how labwc auto-nests from WAYLAND_DISPLAY (labwc is wlroots and nests implicitly; KWin needs the flag).

Why NOT startplasma-wayland (the RCA). In a systemd-less pod startplasma-wayland falls back to the legacy plasma_session shim, which brings KWin up on the HEADLESS backend — KWin holds NO connection to pixelflux’s wayland-1 and opens NO /dev/dri, so it composites into an off-screen buffer nothing captures and the stream is a uniform BLACK frame (a 4046-byte PNG, luma spread 0). Switching to the direct --wayland-display launch fixed it: real composited content (a 45746-byte frame, full luma range 16–235). Two supporting requirements: (1) cap_sys_nice is stripped from kwin_wayland at build (the kde-selkies-strip-caps step) so the launcher can exec it directly under the pod’s no-new-privileges, which rejects exec of a file-cap binary (Operation not permitted); (2) plasmashell is launched on wayland-0 once kwin creates it. PROVEN on check-selkies-kde-pod: full R10 live-check pass (159 passed / 0 failed), the frame-not-black + agent-check confirming a real KWin-composited Plasma desktop, verified visually (Chrome maximized + Plasma panel).

wl: verb coverage on KWin — kdotool works, wlroots tooling doesn’t. The wl check verb DISPATCHES on KWin via kdotool (KWin’s own D-Bus/KWin-script window automation): wl: status reports compositor: kwin, proven passing on check-selkies-kde-pod. What does NOT work on KWin is the wlroots-only tooling — wtype needs zwp_virtual_keyboard_manager_v1, wl-copy/wl-paste need wlr-data-control, wlr-randr needs wlr-output-management (all unimplemented by KWin, so each HANGS) — so plugin-wl is compositor-aware (detectCompositor): those wlroots paths FAIL-FAST on KWin instead of hanging, while the kdotool paths run. The bed authors no wl: clipboard/input/resolution probes (labwc doesn’t lean on them either), but wl: status + kdotool window automation are live and asserted.

Chrome is a supervised selkies-core service. Chrome is launched and supervised by the [program:chrome] supervisord service defined in selkies-core (shared by both flavors — labwc and KDE) — NOT by kde-selkies-session and not by the compositor autostart. The service runs chrome-wrapper with WAYLAND_DISPLAY=wayland-0, restart: always (relaunches on any exit, including the clean exit 0 of the nested-compositor startup race), start_secs: 5 + start_retries: 3 (the single >5s startup-race self-exit resets the retry budget so it never trips FATAL), and priority: 30. autostart defaults true and is self-synchronizing — chrome-wrapper itself polls for the wayland-0 client socket that kwin publishes, so no per-flavor handoff is needed. Chrome works headless under KDE; cdp-proxy proxies its CDP backend.

Encoder is auto-selected at runtime (one box, every GPU config)

Section titled “Encoder is auto-selected at runtime (one box, every GPU config)”

pixelflux picks the H.264 encoder at runtime from the host render node — it uses libva directly (NOT gstreamer; no gst-vaapi element is installed):

  • AMD / Intel render node (DRINODE=/dev/dri/renderD*, auto-injected) → hardware VAAPI (Mesa radeonsi; vainfo shows VAProfileH264*: VAEntrypointEncSlice). So the cachyos base image VAAPI-encodes on an AMD/Intel host — “CPU” and “AMD” are the SAME box, not two.
  • No usable render node → software x264.
  • NVIDIANVENC, but only from the *-nvidia box whose pixelflux is built un-stubbed against the cuda-arch-builder (the cachyos GPU base’s pixelflux stubs NVENC). NVENC is proven INSIDE the GPU-passthrough VM (the RTX-class card is vfio-bound, invisible to a host pod), never as a host pod.
Box Base Encoder venue
selkies-kde cachyos host pod → VAAPI (AMD/Intel) or x264 (check-selkies-kde-pod)
selkies-kde-nvidia cachyos.nvidia (cuda-arch-builder) nested pod in the GPU-passthrough VM → NVENC (check-selkies-kde-nvidia-vm, requires_exclusive: [nvidia-gpu])

The labwc sibling (selkies-labwc / selkies-labwc-nvidia) mirrors this exactly on the selkies-desktop metalayer.