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: theselkiestransport (pixelflux ownswayland-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 tolabwc):require: [selkies, kde-shell, pipewire, dbus]; a single supervisord service (kde-selkies-session, priority 12,scope: user) that polls for/tmp/wayland-1then launcheskwin_wayland --wayland-display wayland-1DIRECTLY (nested) +plasmashellon kwin’swayland-0— see the De-SDDM section for why NOTstartplasma-wayland.kde-shell— the SDDM-free Plasma SESSION package leaf (plasma-desktop deps-puller + kwin_wayland + plasmashell + the core session components + curated apps), shared bykde-desktop(bare-metal SDDM seat) andkde-selkies(headless pod). Workstation-only extras (kdeconnect, bluedevil, partition tools, kwallet, …) stay inkde-desktopso the streaming pod stays lean.selkies-kde-desktop(this metalayer) =selkies-core+kde-selkies(which pullskde-shelltransitively). 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;vainfoshowsVAProfileH264*: 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.
- NVIDIA → NVENC, but only from the
*-nvidiabox whose pixelflux is built un-stubbed against thecuda-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.
Images + test venues
Section titled “Images + test venues”| 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.
Related
Section titled “Related”/charly-selkies:selkies— the pixelflux/selkies streaming transport (the core)./charly-selkies:selkies-desktop-layer— the labwc sibling flavor./charly-selkies:labwc— the labwc nested-compositor primitive (the other seam)./charly-distros:cachyos,/charly-distros:nvidia— the CPU + GPU bases./charly-check:check— the disposable check beds (disposable: truedeploys) that prove each flavor./charly-internals:disposable—requires_exclusive/preemptible(the GPU-VM bed preempts the operator workstation for the single passthrough GPU).