Files
nix-config/docs/uwsm-niri-integration.md
Thomas Syms ca62a6bd19 Add Niri desktop configuration with integrated utilities
- Introduced a new power menu script using fuzzel for session management.
- Updated Bellerophon configuration to include Niri desktop and its components.
- Removed obsolete README for Niri and consolidated its configuration files.
- Added swayidle and swaylock integration for idle management and screen locking.
- Implemented waybar for status bar functionality with basic configuration.
- Created fuzzel integration for application launching and menu access.
- Added zenbook debugging scripts for display and keyboard diagnostics.
- Migrated keyring and other configurations to streamline Niri setup.
- Enhanced display management with systemd services for better integration.
2025-10-02 13:16:27 -03:00

8.0 KiB

UWSM Integration with Niri

Status: FULLY INTEGRATED

This Niri configuration has been fully migrated to use UWSM (Universal Wayland Session Manager) for comprehensive systemd-based session management.

All components now use UWSM:

  • Session launch via programs.uwsm.waylandCompositors
  • Startup applications via systemd.user.services with graphical-session.target
  • Application launches via uwsm app -- wrapper (for proper systemd slice placement)
  • Fuzzel launcher configured with UWSM launch-prefix

Overview

UWSM (Universal Wayland Session Manager) is a systemd-based session manager that provides:

  1. Proper environment variable inheritance - Ensures environment variables from login shells, PAM, and system profiles are properly propagated to the Wayland session and all child processes
  2. Systemd integration - Wraps the compositor in proper systemd units with lifecycle management
  3. XDG autostart support - Handles XDG autostart applications with proper slices and dependencies
  4. Clean startup/shutdown - Manages session lifecycle with proper cleanup on exit
  5. Session binding - Can bind session lifecycle to login shell PID for proper TTY management

Benefits for Niri

Currently, our Niri setup uses:

  • programs.niri.settings.spawn-at-startup for starting applications like nm-applet
  • programs.waybar.systemd.enable = true for waybar systemd service
  • Manual systemd user services for various components

With UWSM:

  • All startup applications would be managed consistently through systemd units
  • Environment variables would be properly inherited from login shell → PAM → systemd → compositor → applications
  • Better integration with systemd targets (graphical-session.target, etc.)
  • Proper cleanup on logout/shutdown
  • XDG autostart applications would work automatically
  • Better compatibility with applications that expect standard Wayland session management

Implementation Plan

1. Host-Level Changes (hosts/common/optional/niri.nix)

Add UWSM package and configure it:

environment.systemPackages = with pkgs; [
  uwsm
];

Enable UWSM mode for Niri (if the niri-flake supports it), or configure it manually.

2. User-Level Changes (home/panotaka/common/optional/desktops/niri/)

Remove manual spawn-at-startup entries and rely on:

  • Systemd user services with WantedBy=graphical-session.target
  • XDG autostart desktop entries
  • UWSM's built-in environment preparation

Option B: Hybrid Approach

Keep some spawn-at-startup for compositor-specific tools, but use UWSM for:

  • Environment variable management
  • Session lifecycle binding
  • XDG autostart apps

3. Migration Path

  1. Phase 1: Add UWSM package and test manual invocation

    uwsm start -o niri
    systemctl --user start wayland-wm@niri.service
    
  2. Phase 2: Migrate startup applications to systemd services

    • Convert spawn-at-startup entries to systemd.user.services
    • Use WantedBy = ["graphical-session.target"] for dependency
  3. Phase 3: Create UWSM desktop entry for display managers

    [Desktop Entry]
    Name=Niri (with UWSM)
    Comment=Niri Wayland compositor with UWSM session management
    Exec=uwsm start -D niri -N Niri -C "Niri compositor" -- niri
    Type=Application
    DesktopNames=niri
    
  4. Phase 4: Configure environment finalization

    • Have Niri execute uwsm finalize in its config to propagate compositor-specific variables

Current State

What Uses spawn-at-startup Currently:

  • Restart policies for resilience

3. Application Launches → UWSM App Wrapper

All applications launched from Niri now use uwsm app -- wrapper:

  • Fuzzel launcher: uwsm app -- fuzzel
    • Also configured with launch-prefix = "uwsm app -- " so apps launched from fuzzel are properly managed
  • Swaylock: uwsm app -- swaylock (Mod+L keybind)
  • Zenbook tools: uwsm app -- zenbook-set-displays (Mod+Z keybind)

This ensures all applications are placed in the correct systemd slices (app-graphical.slice) and inherit proper environment variables.

Files Modified

  1. hosts/common/optional/niri.nix

    • Replaced manual desktop entries with programs.uwsm module
    • Configured Niri as a UWSM-managed compositor
  2. home/panotaka/common/optional/desktops/niri/waybar.nix

    • Migrated nm-applet from spawn-at-startup to systemd.user.services.nm-applet
  3. home/panotaka/common/optional/desktops/niri/zenbook-screen.nix

    • Migrated all zenbook display management tools to systemd services:
      • zenbook-autostart (oneshot initial setup)
      • zenbook-delayed-setup (delayed secondary setup)
      • zenbook-inotify-monitor (long-running DRM status watcher)
      • zenbook-udev-monitor (long-running udev event watcher)
    • Updated Mod+Z keybind to use uwsm app --
  4. home/panotaka/common/optional/desktops/niri/fuzzel.nix

    • Updated keybind to launch fuzzel via uwsm app --
    • Added launch-prefix = "uwsm app -- " to fuzzel config
  5. home/panotaka/common/optional/desktops/niri/swaylock.nix

    • Updated Mod+L keybind to launch swaylock via uwsm app --

Files Modified

  1. home/panotaka/common/optional/desktops/niri/waybar.nix

    • Migrated nm-applet from spawn-at-startup to systemd.user.services.nm-applet
  2. home/panotaka/common/optional/desktops/niri/zenbook-screen.nix

What Already Uses Systemd:

  • programs.waybar.systemd.enable = true
  • polkit-kde-authentication-agent-1

Recommendation

For now, I recommend a soft introduction of UWSM:

  1. Add UWSM package to the system so it's available
  2. Document how to use it (this file)
  3. Keep current setup working as-is
  4. Provide opt-in migration path for users who want systemd-managed session

Later, when fully tested, we can:

  • Make UWSM the default
  • Migrate all startup apps to systemd services
  • Remove manual spawn-at-startup entries
  • Add UWSM desktop entry for GDM/SDDM

Systemd User Services (graphical-session.target)

These services start automatically when the graphical session begins:

  • waybar (via programs.waybar.systemd.enable)
  • nm-applet (network manager applet for tray)
  • polkit-kde-authentication-agent-1 (authentication dialogs)
  • zenbook-autostart (initial display setup)
  • zenbook-delayed-setup (secondary setup after delay)
  • zenbook-inotify-monitor (DRM status change monitoring)
  • zenbook-udev-monitor (udev event monitoring)

Monitoring and Debugging

Check Service Status

# List all graphical session services
systemctl --user list-units --type=service | grep graphical

# Check specific service
systemctl --user status nm-applet
systemctl --user status zenbook-autostart

# View logs
journalctl --user -u nm-applet -f
journalctl --user -u zenbook-inotify-monitor -f

UWSM Session Management

# Check current UWSM session
uwsm status

# List UWSM-managed units
systemctl --user list-units 'wayland-*'

# Stop session cleanly
uwsm stop

Troubleshooting

Service Not Starting

# Check why service failed
systemctl --user status <service-name>
journalctl --user -u <service-name> -n 50

# Manually start for testing
systemctl --user start <service-name>

Environment Variables Missing

UWSM should automatically propagate environment variables. If something is missing:

# Check what's in systemd's environment
systemctl --user show-environment

# Manually import if needed (shouldn't be necessary with UWSM)
systemctl --user import-environment VARIABLE_NAME

Testing UWSM

To test UWSM without changing your current setup:

# Generate units without starting
uwsm start -o niri

# Check generated units
systemctl --user list-units 'wayland-*'

# Start manually
systemctl --user start wayland-wm@niri.service

# Stop
uwsm stop

References