Linux and Wayland Support
Wavry is built to deliver the best Wayland support on the market for latency-first remote sessions.
This guide documents exactly how Linux support works today, what is required on host systems, and how to validate production readiness.
Linux Support Scope
Wavry Linux support is designed around:
- Native Wayland capture through the XDG Desktop Portal + PipeWire path.
- X11 capture fallback for classic X11 sessions.
- GStreamer-based encode/decode pipelines with hardware acceleration when available.
- Practical operations tooling so Linux deployments are observable and repeatable.
Runtime Architecture on Linux
For host capture, Wavry chooses a capture path by session type:
| Session Type | Primary Video Path | Audio Path | Notes |
|---|---|---|---|
| Wayland | xdg-desktop-portal screencast -> pipewiresrc | Portal/PipeWire first, PulseAudio fallback where needed | Native Wayland path, no X11 dependency required |
| X11 | ximagesrc (with optional monitor crop) | PulseAudio/auto source | Legacy path for non-Wayland sessions |
For desktop UI rendering, Wavry enforces Wayland runtime defaults on Wayland sessions:
GDK_BACKEND=waylandWINIT_UNIX_BACKEND=waylandWEBKIT_DISABLE_DMABUF_RENDERER=1WEBKIT_DISABLE_COMPOSITING_MODE=1
This avoids mixed GTK/Winit backend behavior and reduces compositor protocol errors on KDE Plasma Wayland.
Host startup on Linux now performs runtime preflight before capture starts:
- Verifies required Linux capture backend/plugin availability.
- Verifies at least one H264 encoder path is available.
- Resolves capture resolution from the selected monitor instead of forcing a fixed 1080p default.
- Exposes diagnostics/preflight commands (
linux_runtime_health,linux_host_preflight) for desktop UX and support tooling.
Prerequisites by Distribution
Ubuntu / Debian
sudo apt-get update
sudo apt-get install -y \
pkg-config protobuf-compiler \
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
libasound2-dev libx11-dev libxtst-dev libxrandr-dev libxi-dev libevdev-dev libudev-dev \
libgtk-3-dev libwebkit2gtk-4.1-dev libsoup-3.0-dev libayatana-appindicator3-dev librsvg2-dev libgl-dev \
pipewire pipewire-pulse xdg-desktop-portal
Install your desktop-specific portal backend:
- GNOME:
xdg-desktop-portal-gnome - KDE Plasma:
xdg-desktop-portal-kde - wlroots compositors:
xdg-desktop-portal-wlr
Fedora
sudo dnf install -y \
pkg-config protobuf-compiler \
gstreamer1-devel gstreamer1-plugins-base-devel \
alsa-lib-devel libX11-devel libXtst-devel libXrandr-devel libXi-devel libevdev-devel systemd-devel \
gtk3-devel webkit2gtk4.1-devel libsoup3-devel libappindicator-gtk3-devel librsvg2-devel mesa-libGL-devel \
pipewire pipewire-pulseaudio xdg-desktop-portal
Then add the matching portal backend package for your desktop environment.
Arch Linux
sudo pacman -S --needed \
base-devel pkgconf protobuf \
gst-plugins-base-libs gstreamer \
alsa-lib libx11 libxtst libxrandr libxi libevdev libudev0-shim \
gtk3 webkit2gtk libsoup3 libappindicator-gtk3 librsvg mesa \
pipewire pipewire-pulse xdg-desktop-portal
Add one backend package:
xdg-desktop-portal-gnomexdg-desktop-portal-kdexdg-desktop-portal-wlr
Distro Runbooks (Operations)
Use these when Linux hosts fail capture/startup and you need deterministic recovery.
Ubuntu / Debian runbook
- Verify portal + PipeWire processes:
pgrep -a xdg-desktop-portal || true
pgrep -a xdg-desktop-portal-gnome || true
pgrep -a xdg-desktop-portal-kde || true
pgrep -a xdg-desktop-portal-gtk || true
pgrep -a pipewire || true
- Verify required GStreamer components:
gst-inspect-1.0 pipewiresrc
gst-inspect-1.0 x264enc
gst-inspect-1.0 opusenc
- Run Wavry preflight:
./scripts/linux-display-smoke.sh
Fedora runbook
- Verify portal backend package selection:
rpm -qa | rg "xdg-desktop-portal|pipewire|gstreamer1"
- Verify active user services:
systemctl --user status xdg-desktop-portal.service --no-pager
systemctl --user status xdg-desktop-portal-gnome.service --no-pager || true
systemctl --user status xdg-desktop-portal-kde.service --no-pager || true
systemctl --user status xdg-desktop-portal-wlr.service --no-pager || true
- Run Wavry preflight:
./scripts/linux-display-smoke.sh
Arch Linux runbook
- Verify portal descriptor files:
ls /usr/share/xdg-desktop-portal/portals
- Verify session environment:
echo "XDG_SESSION_TYPE=$XDG_SESSION_TYPE"
echo "XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP"
echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
- Run Wavry preflight:
./scripts/linux-display-smoke.sh
Session and Compositor Compatibility
| Platform Stack | Status | Notes |
|---|---|---|
| KDE Plasma + Wayland | First-class | Native portal/PipeWire capture path |
| GNOME + Wayland | First-class | Native portal/PipeWire capture path |
| Sway/Hyprland/wlroots + Wayland | Supported with correct portal backend | Requires xdg-desktop-portal-wlr and PipeWire |
| X11 desktops | Supported | Uses X11 capture pipeline |
Validation Workflow
1. Build-time checks
cargo check -p wavry-media
cargo check -p wavry-desktop
2. Linux display smoke test
./scripts/linux-display-smoke.sh
This script validates command availability, key GStreamer elements, expected portal backend descriptors, portal process health, and session context before runtime testing.
3. Runtime confirmation
cd crates/wavry-desktop
RUST_LOG=info bun run tauri dev
For Wayland sessions, confirm logs include native stream selection and no protocol-dispatch errors. The app also logs Linux runtime diagnostics on startup (session type, backend choice, missing plugin hints).
Troubleshooting Checklist (Wayland)
If capture or startup fails on Wayland:
- Confirm
xdg-desktop-portalis running in the user session. - Confirm the desktop-specific portal backend package is installed and active.
- Confirm PipeWire is running and healthy.
- Confirm capture permission prompt was granted by the portal.
- Re-run
./scripts/linux-display-smoke.shand fix all failing checks.
If the app reports that Wayland portal probing failed, treat this as a host configuration issue first (portal backend, permissions, or PipeWire state).
Failure Matrix
| Symptom | Likely Cause | Where to Confirm | Corrective Action |
|---|---|---|---|
Gdk-Message ... Error 71 (Protocol Error) dispatching to wayland display | Mixed GTK/WebKit backend mode | Desktop startup logs | Ensure Wavry runtime env overrides are active; relaunch app |
Wayland session detected but portal monitor probe failed | Missing/inactive portal backend | linux_runtime_health + linux-display-smoke.sh | Install correct backend package and restart portal services |
| No monitors in host card | Portal permission denied or stale | Desktop logs + portal prompt history | Re-grant screencast permission, then refresh monitors |
Host start fails with missing pipewiresrc | Missing GStreamer plugin package | gst-inspect-1.0 pipewiresrc | Install PipeWire GStreamer plugin set |
| Host start fails with no H264 encoder | Missing encoder plugin | gst-inspect-1.0 x264enc (or VAAPI/NVENC plugin) | Install software/hardware encoder plugin package |
| Linux package installs but app fails to launch | Missing runtime libs on target distro | ldd / distro package manager logs | Install required WebKitGTK/GTK/GStreamer runtime deps |
Production Guidance for Linux Hosts
- Pin compositor and portal backend versions in production images.
- Track and alert on portal failures and relay/direct ratio changes.
- Keep GStreamer plugin sets consistent across host fleets.
- Validate every release on at least one GNOME Wayland host and one KDE Wayland host.
- Keep an X11 validation lane only for legacy desktops, not as the primary path.
Security and Privacy Notes
- Wavry relies on portal-mediated capture on Wayland, which enforces user permission boundaries.
- Session media transport remains end-to-end encrypted through the RIFT stack.
- Do not run production hosts with ad-hoc desktop permissions or unknown portal backends.