Categories
DevOps & Cloud Infrastructure Software Development

Improving Linux Resilience by Separating Wayland Components

Discover how separating the Wayland compositor and window manager improves Linux system resilience, security, and flexibility in production environments.

Why Separate the Wayland Compositor and Window Manager?

The Linux desktop’s move from X11 to Wayland has been a long-standing project aiming to simplify graphics, reduce latency, and resolve decades-old architectural problems. Traditionally, Wayland compositors have combined the roles of display server, compositor, and window manager into a single, monolithic process. This all-in-one approach solved input routing and rendering performance issues inherent in X11, but at a cost: it made customizing window management logic far more complex and discouraged experimentation and diversity in window manager design.

The River project—a non-monolithic Wayland compositor—breaks from this tradition. By splitting the window manager out into a separate client process, River allows window managers to be developed, swapped, and debugged independently of the compositor core. This separation is made possible by the river-window-management-v1 protocol, which gives full control over window placement, keybindings, server-side decorations, and other policy decisions to the external window manager, while the compositor remains focused on rendering, input routing, and performance guarantees.

This shift is not academic. For DevOps and SREs managing production Linux desktops or kiosks, the separation unlocks several tangible benefits:

  • Crash resilience: A window manager crash no longer takes down the entire display server.
  • Dynamic reconfiguration: Window managers (even written in high-level, garbage-collected languages) can be hot-swapped or updated without restarting the compositor or disrupting user sessions.
  • Security: Policy and rendering can be sandboxed and upgraded independently, reducing attack surface.
  • Lower barrier to entry: Developers can rapidly prototype new window management paradigms without the complexity of compositor internals.

But this architectural split is not without its own challenges—especially around protocol design, synchronization, and production hardening. The rest of this article unpacks these concerns with practical, production-focused guidance and real-world configuration examples.

Wayland Architecture: Monolithic vs. Modular

To understand the implications of separating compositor and window manager, it’s essential to contrast the two models. The table below summarizes the key differences:

AspectMonolithic Compositor (e.g., Sway, Weston)Modular Compositor (e.g., River + External WM)
Window ManagementImplemented inside the compositor process; tightly coupledSeparate client process communicates via protocol (e.g., river-window-management-v1)
Crash ImpactWindow manager crash brings down the compositor/sessionWindow manager crash can be recovered without losing session
ExtensibilityRequires forking or patching the compositorNew window managers can be developed and swapped independently
Language SupportTypically C/C++/Rust; garbage collection risky due to latencyCan use high-level languages safely (latency isolated from compositor)
PerformancePotentially lower IPC overhead, but harder to isolate slow codeMinimal IPC overhead; “frame perfection” achievable with careful protocol design
SecurityAll policy and rendering in one process; larger attack surfacePolicy can be sandboxed, reducing compositor’s privileges

Reference: Isaac Freund, River project

You landed the Cloud Storage of the future internet. Cloud Storage Services Sesame Disk by NiHao Cloud

Use it NOW and forever!

Support the growth of a Team File sharing system that works for people in China, USA, Europe, APAC and everywhere else.

Protocol Challenges: Frame Perfection and Latency

The critical challenge in modularizing window management is maintaining frame perfection—ensuring that window changes (e.g., tiling layout updates) are applied atomically, avoiding flicker, gaps, or input lag. The river-window-management-v1 protocol addresses this by batching state changes and synchronizing rendering only when all windows have submitted new buffers, with short timeouts to avoid stalling the compositor. Unlike the X11 model (where async communication could lead to visible artifacts), River’s protocol ensures there are no extra round-trips on every frame or input event.

Production-Ready Configuration: Separating Compositor and Window Manager

Let’s walk through deploying River with an external window manager. We’ll focus on security, operational best practices, and realistic configurations—not just “hello world.”

1. Installing Dependencies

River is written in Zig and depends on wlroots, wayland, and other libraries. For production, use a recent LTS distribution and pinned package versions to avoid breakage:

# Ubuntu 24.04+ or Fedora 39+ recommended
sudo apt install zig wlroots-dev libxkbcommon-dev libevdev-dev libpixman-1-dev pkg-config
# For Xwayland compatibility (optional, but often needed):
sudo apt install xwayland

Note: River requires Zig 0.15 or later. Confirm with:

zig version
# Output should be >= 0.15

2. Building and Installing River

git clone https://github.com/gnuunixchad/river.git
cd river
zig build -Doptimize=ReleaseSafe --prefix ~/.local install

For system-wide install, use sudo or package River as an RPM/DEB with custom hardening flags (see PACKAGING.md).

3. Configuring River to Launch a Window Manager

On startup, River executes the script at $XDG_CONFIG_HOME/river/init (falls back to ~/.config/river/init). This script should launch your chosen window manager, set up environment variables, and start essential services (e.g., dbus, polkit agent).

#!/bin/sh
# ~/.config/river/init

# Hardening: run the window manager in a restricted user namespace
unshare -n -- bash -c '
  export WAYLAND_DISPLAY=wayland-1
  # Example: start tinyrwm (a minimal river-compatible window manager)
  exec tinyrwm
'
# Start background services (replace with your actual agents)
dbus-run-session -- systemctl --user start polkit-gnome-authentication-agent-1.service

Security tips:

  • Run the window manager with reduced privileges (no unnecessary CAP_*).
  • Restrict file access using systemd --user units with ProtectHome=yes, ProtectSystem=strict.
  • Never start Xwayland or legacy X clients unless absolutely necessary.

4. Example: Switching Window Managers on the Fly

One of the advantages of River is hot-swapping window managers without restarting the session. Assuming you have both tinyrwm and canoe installed, you can kill the current window manager and start another:

# Find and kill the current window manager (replace 'tinyrwm' if using another)
pkill -f tinyrwm
# Start canoe in the same session
canoe &

No windows or user sessions are lost in the process—only window management policy is swapped.

Operational Considerations: Monitoring, Security, and Hot-Swapping

Running a production Wayland session with a split compositor and window manager model introduces new operational challenges. Here’s how to address them:

Monitoring and Logging

  • Configure river and your window manager to log to systemd-journald with StandardOutput=journal.
  • Set up health checks to ensure both processes remain alive (e.g., systemd --user units with Restart=on-failure).
  • Aggregate logs for both compositor and window manager for holistic visibility.

Security Hardening Checklist

  • Use seccomp and AppArmor profiles to sandbox the window manager process.
  • Run the compositor and window manager as the non-root user.
  • If possible, use user namespaces to further isolate window management logic.
  • Review upstream security advisories for Wayland protocol extensions in use.

Hot-Swapping and Upgrades

  • Test window manager upgrades in a nested Wayland/X11 session before deploying to production (River supports running nested).
  • Keep a fallback window manager binary available in case of failed upgrades.
  • Automate window manager restart policies using systemd --user:
[Unit]
Description=River Window Manager

[Service]
ExecStart=/usr/local/bin/tinyrwm
Restart=on-failure
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes

[Install]
WantedBy=default.target

Troubleshooting: Common Errors and Solutions

Splitting the compositor and window manager can introduce new classes of failure. Here are the most common, with actionable fixes:

  • Window manager does not start or crashes immediately:

    • Check the river log and the window manager’s stdout/stderr for protocol version mismatches.
    • Ensure the window manager supports the river-window-management-v1 protocol version your compositor provides. Upgrade/rebuild as necessary.
  • No windows managed or keybindings unresponsive:

    • Verify that the window manager is running (e.g., ps aux | grep tinyrwm).
    • Check your init script for typos or failed background service launches.
    • Ensure input devices are correctly configured in river (use riverctl for runtime inspection).
  • Visual artifacts, flicker, or layout gaps:

    • If using a custom window manager, check its buffer submission and state batching logic. Delays in buffer updates can cause temporary gaps.
    • Refer to design documentation on “frame perfection.”
  • “Permission denied” errors launching Xwayland clients:

    • Make sure Xwayland is installed and configured for non-root users.
    • Limit Xwayland launch to only trusted applications; do not run X clients as root.
  • Input devices not working:

    • Check device permissions (/dev/input/* should be accessible to the user running river).
    • Use udev rules to ensure persistent device access.

Trade-offs and Alternatives

While River’s approach is the most advanced split-compositor model in production today, it’s not the only one. Here’s how alternatives stack up:

Compositor/WMArchitectureBenefitsDrawbacks
River + External WMModular (split)Crash resilience, language flexibility, hot-swapping, lower entry barrierProtocol maturity, fewer “fancy” shell features, limited VR/3D support
SwayMonolithicMature, i3-like, robust wlroots integrationMust fork for major WM changes; WM crash loses session
WestonMonolithicReference compositor, stabilityCustomization requires patching core
MusaHybrid (external WMs supported, early stage)First-class multiseat, WM extensibilityLess mature, smaller ecosystem

For most production deployments, River is currently the only split-compositor viable for daily use, but this will likely change as protocol maturity and window manager diversity increase.

Key Takeaways

Key Takeaways:

  • Separating the Wayland compositor and window manager makes Linux desktop and kiosk deployments more resilient, flexible, and secure.
  • The river-window-management-v1 protocol enables frame-perfect, low-latency window management by batching state changes and decoupling policy from rendering.
  • Crash recovery, hot-swapping window managers, and language flexibility are immediate operational benefits—but require careful protocol and process management.
  • Security hardening is essential: sandbox window managers, avoid unnecessary privileges, and monitor for protocol compatibility and process health.
  • Alternatives like Sway (monolithic) offer stability and ecosystem maturity, but at the cost of extensibility and resilience.

For further reading on protocol details, configuration, and the River project’s roadmap, see Isaac Freund’s blog and the River GitHub repository.

By Rafael

I am Just Rafael, but with AI I feel like I have supper powers.

Start Sharing and Storing Files for Free

You can also get your own Unlimited Cloud Storage on our pay as you go product.
Other cool features include: up to 100GB size for each file.
Speed all over the world. Reliability with 3 copies of every file you upload. Snapshot for point in time recovery.
Collaborate with web office and send files to colleagues everywhere; in China & APAC, USA, Europe...
Tear prices for costs saving and more much more...
Create a Free Account Products Pricing Page