Niri Scrollable Tiling Compositor: NVIDIA + Noctalia Shell

// derivatives

Niri Scrollable Tiling Compositor: NVIDIA + Noctalia Shell

Rust-written scrollable-tiling Wayland compositor with infinite horizontal window strips

# Niri Installation Guide

NVIDIA | Noctalia Shell | Recommended Applications

Prerequisites: A working Arch Linux base installation with NVIDIA drivers, iwd, and NetworkManager already configured. Niri’s NVIDIA setup assumes nvidia-drm.modeset=1 is already set in your GRUB cmdline and nvidia modules are in your initramfs — both covered in the Arch install guide.

Table of Contents

1. [What is Niri?](#1-what-is-niri) 2. [Install Niri and Core Dependencies](#2-install-niri-and-core-dependencies) 3. [NVIDIA Configuration](#3-nvidia-configuration) 4. [Install Recommended Applications](#4-install-recommended-applications) 5. [config.kdl — Full Configuration](#5-configkdl–full-configuration) 6. [Noctalia Shell](#6-noctalia-shell) 7. [Showing Keybinds](#7-showing-keybinds) 8. [Setting Default Applications](#8-setting-default-applications) 9. [Enable Services](#9-enable-services) 10. [Starting Niri](#10-starting-niri) 11. [NVIDIA Troubleshooting](#11-nvidia-troubleshooting)

1. What is Niri?

Niri is a scrollable-tiling Wayland compositor written in Rust. Unlike traditional tiling compositors where opening a new window reshuffles all existing windows, Niri places every window in its own column on an infinite horizontal strip. You scroll left and right to reveal windows — existing layouts never change when a new window opens.

Key characteristics: – Scrollable tiling — windows sit in columns; scroll horizontally to navigate – Per-monitor workspaces — each display has its own independent window strip and vertical stack of workspaces; windows cannot bleed between displays – Dynamic workspaces — workspaces are created and destroyed automatically as you use them – Live config reload — edit config.kdl, save, and changes apply instantly – Built-in screenshot UI — region, screen, and window capture with no extra tools – Built-in hotkey overlay — press a key to see all your bindings on screen – Touchpad and mouse gestures — swipe to switch workspaces, scroll to navigate columns – KDL config language — clean, minimal syntax with inline comments – Inspired by GNOME’s PaperWM, but a standalone compositor rather than an extension

2. Install Niri and Core Dependencies

Niri is in the official Arch extra repository. An AUR helper (yay or paru) is needed for Noctalia and a few supporting packages.

Install yay (AUR helper)

sudo pacman -S --needed git base-devel
git clone https://aur.archlinux.org/yay.git /tmp/yay
cd /tmp/yay && makepkg -si

Core Niri packages

sudo pacman -S niri \
  xwayland-satellite \
  xdg-desktop-portal-gnome \
  xdg-desktop-portal-gtk \
  qt5-wayland qt6-wayland
| Package | Purpose | |—|—| | niri | The compositor itself | | xwayland-satellite | Rootless XWayland — runs X11 apps (Steam, Discord, etc.) without a full X server | | xdg-desktop-portal-gnome | Required for screencasting and screen sharing | | xdg-desktop-portal-gtk | File chooser and other portal dialogs | | qt5-wayland / qt6-wayland | Qt Wayland platform support |

Audio stack

sudo pacman -S pipewire pipewire-alsa pipewire-pulse pipewire-jack \
  wireplumber pavucontrol playerctl

systemctl --user enable --now pipewire pipewire-pulse wireplumber

Fonts

sudo pacman -S noto-fonts noto-fonts-emoji noto-fonts-cjk \
  ttf-jetbrains-mono-nerd ttf-font-awesome

XDG and theming tools

sudo pacman -S xdg-utils xdg-user-dirs nwg-look qt6ct
xdg-user-dirs-update

3. NVIDIA Configuration

modprobe options

If you have not already created /etc/modprobe.d/nvidia.conf from the Arch install guide, do so now:

sudo nano /etc/modprobe.d/nvidia.conf
options nvidia-drm modeset=1
options nvidia NVreg_PreserveVideoMemoryAllocations=1

Rebuild initramfs:

sudo mkinitcpio -P

NVIDIA VRAM fix

NVIDIA has a driver quirk where it does not release VRAM properly in Wayland compositors. Create the following profile to fix it:

sudo mkdir -p /etc/nvidia/nvidia-application-profiles-rc.d
sudo nano /etc/nvidia/nvidia-application-profiles-rc.d/50-niri-vram.json
{
  "rules": [
    {
      "pattern": { "feature": "procname", "matches": "niri" },
      "profile": "niri-vram-fix"
    }
  ],
  "profiles": [
    {
      "name": "niri-vram-fix",
      "settings": [
        {
          "key": "GLVidHeapReuseRatio",
          "value": 0
        }
      ]
    }
  ]
}

NVIDIA environment variables

These are set inside config.kdl in the environment {} block (section 5) so they apply to all processes Niri spawns. No system-wide changes are needed beyond the modprobe options above.

Note: __GLX_VENDOR_LIBRARY_NAME "nvidia" occasionally causes login failures on some NVIDIA setups. If Niri fails to start, comment that line out first and test without it.

4. Install Recommended Applications

Terminal — foot

sudo pacman -S foot

foot is a minimal, fast, purpose-built terminal for tiling Wayland compositors. It starts noticeably faster than kitty or alacritty for frequent spawning. Config: ~/.config/foot/foot.ini.

Also install alacritty as an alternative:

sudo pacman -S alacritty

App launcher — fuzzel

sudo pacman -S fuzzel

fuzzel is Niri’s default launcher. It is Wayland-native, fast, and styled with a simple INI config at ~/.config/fuzzel/fuzzel.ini.

Notification daemon — mako

sudo pacman -S mako

mako is the notification daemon recommended by the Niri wiki. It is lightweight and scriptable. Config: ~/.config/mako/config.

If you install Noctalia Shell (section 6), it handles notifications itself and you do not need to run mako separately.

Screenshot — grim and slurp

sudo pacman -S grim slurp

Niri also has built-in screenshot actions (screenshot, screenshot-screen, screenshot-window) bound to the Print key family. grim and slurp provide additional flexibility for scripted captures.

Clipboard

sudo pacman -S wl-clipboard cliphist

Screen locker — swaylock

sudo pacman -S swaylock

swaylock is the standard sway-ecosystem locker and works cleanly with Niri. The config lives at ~/.config/swaylock/config.

# ~/.config/swaylock/config
image=~/Pictures/Wallpapers/wallpaper.jpg
scaling=fill
blur-radius=7
fade-in=0.2
font=JetBrains Mono Nerd Font
indicator-radius=120
indicator-thickness=10
ring-color=88c0d0
key-hl-color=a3be8c
bs-hl-color=bf616a
inside-color=2e344080
text-color=eceff4

Idle daemon — swayidle

sudo pacman -S swayidle

swayidle handles screen dimming, locking, and suspend after inactivity. It is started from within config.kdl via spawn-at-startup.

Wallpaper — swaybg

sudo pacman -S swaybg

swaybg is a simple, reliable static wallpaper daemon. Started from config.kdl with spawn-sh-at-startup.

File manager — Thunar

sudo pacman -S thunar thunar-archive-plugin thunar-volman gvfs

Image viewer — imv

sudo pacman -S imv

Video player — mpv

sudo pacman -S mpv

Create ~/.config/mpv/mpv.conf for hardware-accelerated decode:

hwdec=vaapi
gpu-api=vulkan

PDF viewer — zathura

sudo pacman -S zathura zathura-pdf-mupdf

Browser — Firefox

sudo pacman -S firefox

Polkit agent — polkit-gnome

sudo pacman -S polkit-gnome

Keyring

sudo pacman -S gnome-keyring libsecret

Brightness control

sudo pacman -S brightnessctl

GTK and Qt theming

sudo pacman -S nwg-look qt6ct
yay -S kvantum

5. config.kdl — Full Configuration

All Niri configuration lives in a single file: ~/.config/niri/config.kdl. It uses KDL (KDL Document Language) — a clean key-value format with // line comments. The file hot-reloads on save.

Create the config directory and file:

mkdir -p ~/.config/niri
nano ~/.config/niri/config.kdl

Full config.kdl

// ============================================================
// ENVIRONMENT VARIABLES
// Applied to all processes spawned by Niri
// ============================================================

environment { // NVIDIA — required for Wayland on NVIDIA hardware GBM_BACKEND "nvidia-drm" // __GLX_VENDOR_LIBRARY_NAME "nvidia" // uncomment if needed; remove if Niri fails to start LIBVA_DRIVER_NAME "nvidia" NVD_BACKEND "direct"

// Wayland session XDG_SESSION_TYPE "wayland" XDG_CURRENT_DESKTOP "niri" XDG_SESSION_DESKTOP "niri"

// Qt — force Wayland QT_QPA_PLATFORM "wayland" QT_QPA_PLATFORMTHEME "qt6ct" QT_WAYLAND_DISABLE_WINDOWDECORATION "1" QT_AUTO_SCREEN_SCALE_FACTOR "1"

// Electron and Chromium — Wayland native ELECTRON_OZONE_PLATFORM_HINT "auto" NIXOS_OZONE_WL "1"

// Cursor XCURSOR_THEME "Adwaita" XCURSOR_SIZE "24"

// Terminal (used by launchers and scripts) TERMINAL "foot" TERM "foot" }

// ============================================================ // INPUT // ============================================================

input { keyboard { xkb { layout "us" } repeat-delay 600 repeat-rate 25 }

touchpad { tap natural-scroll dwt scroll-method "two-finger" accel-speed 0.2 }

mouse { accel-speed 0.0 accel-profile "flat" }

focus-follows-mouse warp-mouse-to-focus }

// ============================================================ // OUTPUTS (monitors) // Run: niri msg outputs — to see monitor names and available modes // ============================================================

output "eDP-1" { mode "1920x1080@60.000" scale 1.0 position x=0 y=0 // variable-refresh-rate // uncomment to enable VRR/FreeSync }

// External monitor example — uncomment and adjust: // output "HDMI-A-1" { // mode "2560x1440@144.0" // scale 1.0 // position x=1920 y=0 // }

// ============================================================ // LAYOUT // ============================================================

layout { gaps 12

center-focused-column "on-overflow"

preset-column-widths { proportion 0.33333 proportion 0.5 proportion 0.66667 proportion 1.0 }

default-column-width { proportion 0.5; }

focus-ring { width 3 active-color "#88c0d0" inactive-color "#4c566a" }

border { off width 2 active-color "#88c0d0" inactive-color "#4c566a" }

shadow { on softness 25 spread 4 offset x=0 y=4 color "#00000060" }

struts { top 0 bottom 0 }

background-color "#1e2030" }

// ============================================================ // WINDOW RULES // ============================================================

// Rounded corners for all windows window-rule { geometry-corner-radius 10 clip-to-geometry true }

// Float common utility windows window-rule { match app-id=r#"pavucontrol"# open-floating true default-floating-size { width 800; height 600; } }

window-rule { match app-id=r#"nm-connection-editor"# open-floating true }

window-rule { match app-id=r#"nwg-look"# open-floating true }

window-rule { match app-id=r#"qt6ct"# open-floating true }

window-rule { match app-id=r#"blueman-manager"# open-floating true }

// Firefox picture-in-picture window-rule { match app-id=r#"firefox"# title=r#"Picture-in-Picture"# open-floating true default-floating-size { width 480; height 270; } }

// Idle inhibit when an app is fullscreen (prevent lock during video) window-rule { match is-active=true block-out-from "screen-capture" }

// ============================================================ // NOCTALIA SHELL LAYER RULES // Required for Noctalia wallpaper and overview integration // ============================================================

layer-rule { match namespace=r#"^noctalia-wallpaper.*"# place-within-backdrop true }

layer-rule { match namespace=r#"^noctalia-overview.*"# place-within-backdrop true }

// ============================================================ // MISCELLANEOUS // ============================================================

prefer-no-csd

screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"

hotkey-overlay { skip-at-startup // hide-not-bound // uncomment to only show bound actions }

// Required for Noctalia notification actions to work debug { honor-xdg-activation-with-invalid-serial }

// ============================================================ // AUTOSTART // ============================================================

// D-Bus environment propagation — required for portals and services spawn-at-startup "systemctl" "--user" "import-environment" "WAYLAND_DISPLAY" "XDG_CURRENT_DESKTOP" "XDG_SESSION_TYPE" spawn-at-startup "dbus-update-activation-environment" "--systemd" "WAYLAND_DISPLAY" "XDG_CURRENT_DESKTOP" "XDG_SESSION_TYPE"

// XWayland satellite (X11 app compatibility) spawn-at-startup "xwayland-satellite"

// Polkit agent spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"

// Keyring daemon spawn-sh-at-startup "gnome-keyring-daemon --start --components=secrets,pkcs11"

// Wallpaper (comment out if using Noctalia's built-in wallpaper) spawn-sh-at-startup "swaybg -i ~/Pictures/Wallpapers/wallpaper.jpg -m fill"

// Idle management and screen lock spawn-at-startup "swayidle" "-w" "timeout" "300" "swaylock -f" "timeout" "310" "niri msg action power-off-monitors" "resume" "niri msg action power-on-monitors" "before-sleep" "swaylock -f"

// Notification daemon (comment out if using Noctalia) spawn-at-startup "mako"

// Status bar (comment out if using Noctalia) // spawn-at-startup "waybar"

// Noctalia shell (uncomment after installing Noctalia — see section 6) // spawn-at-startup "qs" "-c" "noctalia-shell"

// Clipboard history watchers spawn-at-startup "wl-paste" "--type" "text" "--watch" "cliphist" "store" spawn-at-startup "wl-paste" "--type" "image" "--watch" "cliphist" "store"

// GTK dark mode spawn-sh-at-startup "gsettings set org.gnome.desktop.interface color-scheme prefer-dark" spawn-sh-at-startup "gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark"

// ============================================================ // KEYBINDS // Format: Mod+Key { action; } // Mod = Super key (on TTY) or Alt (when running nested inside another compositor) // ============================================================

binds { // ---- Applications ---- Mod+Return hotkey-overlay-title="Open Terminal" { spawn "foot"; } Mod+E hotkey-overlay-title="File Manager" { spawn "thunar"; } Mod+B hotkey-overlay-title="Browser" { spawn "firefox"; } Mod+D hotkey-overlay-title="App Launcher" { spawn "fuzzel"; }

// ---- Keybind help ---- Mod+Shift+Slash hotkey-overlay-title="Show This Keybind Overlay" { show-hotkey-overlay; }

// ---- Window management ---- Mod+Q hotkey-overlay-title="Close Window" { close-window; } Mod+F hotkey-overlay-title="Toggle Fullscreen" { fullscreen-window; } Mod+Shift+F hotkey-overlay-title="Toggle Floating" { toggle-window-floating; } Mod+C hotkey-overlay-title="Center Floating Window" { center-window; }

// ---- Overview ---- Mod+O hotkey-overlay-title="Toggle Overview" { toggle-overview; }

// ---- Focus navigation (arrow keys and vim keys) ---- Mod+Left hotkey-overlay-title="Focus Column Left" { focus-column-left; } Mod+Right hotkey-overlay-title="Focus Column Right" { focus-column-right; } Mod+Up hotkey-overlay-title="Focus Window Up" { focus-window-up; } Mod+Down hotkey-overlay-title="Focus Window Down" { focus-window-down; } Mod+H { focus-column-left; } Mod+L { focus-column-right; } Mod+K { focus-window-up; } Mod+J { focus-window-down; }

// Focus first/last column Mod+Home { focus-column-first; } Mod+End { focus-column-last; }

// ---- Move windows ---- Mod+Shift+Left hotkey-overlay-title="Move Column Left" { move-column-left; } Mod+Shift+Right hotkey-overlay-title="Move Column Right" { move-column-right; } Mod+Shift+Up hotkey-overlay-title="Move Window Up" { move-window-up; } Mod+Shift+Down hotkey-overlay-title="Move Window Down" { move-window-down; } Mod+Shift+H { move-column-left; } Mod+Shift+L { move-column-right; } Mod+Shift+K { move-window-up; } Mod+Shift+J { move-window-down; }

// ---- Column width ---- Mod+R hotkey-overlay-title="Cycle Column Width" { switch-preset-column-width; } Mod+Shift+R hotkey-overlay-title="Reset Column Width" { reset-window-height; } Mod+Minus hotkey-overlay-title="Shrink Column" { set-column-width "-10%"; } Mod+Equal hotkey-overlay-title="Expand Column" { set-column-width "+10%"; }

// Consume/expel windows between columns Mod+I hotkey-overlay-title="Consume Window Into Column" { consume-window-into-column; } Mod+U hotkey-overlay-title="Expel Window From Column" { expel-window-from-column; }

// ---- Workspaces ---- Mod+Page_Up hotkey-overlay-title="Focus Workspace Up" { focus-workspace-up; } Mod+Page_Down hotkey-overlay-title="Focus Workspace Down" { focus-workspace-down; } Mod+1 { focus-workspace 1; } Mod+2 { focus-workspace 2; } Mod+3 { focus-workspace 3; } Mod+4 { focus-workspace 4; } Mod+5 { focus-workspace 5; } Mod+6 { focus-workspace 6; } Mod+7 { focus-workspace 7; } Mod+8 { focus-workspace 8; } Mod+9 { focus-workspace 9; }

Mod+Shift+Page_Up hotkey-overlay-title="Move Window to Workspace Up" { move-window-to-workspace-up; } Mod+Shift+Page_Down hotkey-overlay-title="Move Window to Workspace Down" { move-window-to-workspace-down; } Mod+Shift+1 { move-window-to-workspace 1; } Mod+Shift+2 { move-window-to-workspace 2; } Mod+Shift+3 { move-window-to-workspace 3; } Mod+Shift+4 { move-window-to-workspace 4; } Mod+Shift+5 { move-window-to-workspace 5; } Mod+Shift+6 { move-window-to-workspace 6; } Mod+Shift+7 { move-window-to-workspace 7; } Mod+Shift+8 { move-window-to-workspace 8; } Mod+Shift+9 { move-window-to-workspace 9; }

// ---- Screenshots ---- Print hotkey-overlay-title="Screenshot Region" { screenshot; } Ctrl+Print hotkey-overlay-title="Screenshot Screen" { screenshot-screen; } Alt+Print hotkey-overlay-title="Screenshot Window" { screenshot-window; }

// ---- Clipboard history ---- Mod+V hotkey-overlay-title="Clipboard History" { spawn-sh "cliphist list | fuzzel --dmenu | cliphist decode | wl-copy"; }

// ---- Screen lock ---- Mod+Alt+L hotkey-overlay-title="Lock Screen" { spawn "swaylock"; }

// ---- Audio ---- XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "-l" "1.5" "@DEFAULT_AUDIO_SINK@" "0.05+"; } XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.05-"; } XF86AudioPlay allow-when-locked=true { spawn "playerctl" "play-pause"; } XF86AudioNext allow-when-locked=true { spawn "playerctl" "next"; } XF86AudioPrev allow-when-locked=true { spawn "playerctl" "previous"; }

// ---- Brightness ---- XF86MonBrightnessUp { spawn "brightnessctl" "set" "10%+"; } XF86MonBrightnessDown { spawn "brightnessctl" "set" "10%-"; }

// ---- Niri / session ---- Mod+Shift+R hotkey-overlay-title="Reload Config" { reload-config; } Mod+Shift+M hotkey-overlay-title="Quit Niri" { quit; } }

Validate the config

After saving, check for syntax errors without restarting:

niri validate

To apply from a running session:

niri msg action reload-config
# Or press Mod+Shift+R

6. Noctalia Shell

Noctalia is a minimal Wayland desktop shell built on Quickshell (Qt/QML). It runs on top of Niri and provides a unified replacement for:

– Waybar (status bar and panel) – mako / dunst (notifications and notification history center) – wofi / fuzzel (app launcher with spotlight-style search) – swaylock / hypridle (lock screen and idle management) – Clipboard history viewer

It also applies dynamic Material You color theming — when you change your wallpaper, Noctalia recolors the entire shell, GTK apps, Qt apps, and the terminal automatically via matugen.

Install Noctalia

Noctalia and its Quickshell fork (noctalia-qs) are AUR packages:

# Install Noctalia (pulls in noctalia-qs automatically)
yay -S noctalia-shell
Important: Noctalia requires its own Quickshell fork (noctalia-qs). If you have the upstream quickshell or quickshell-git package installed, it conflicts with noctalia-qs. Remove it first: sudo pacman -R quickshell

Additional dependencies

sudo pacman -S brightnessctl imagemagick wlsunset cliphist
yay -S matugen

Update config.kdl for Noctalia

Once Noctalia is installed, update your ~/.config/niri/config.kdl. Replace the mako and swaybg autostart lines and uncomment the Noctalia line:

// Comment out or remove these lines:
// spawn-at-startup "mako"
// spawn-sh-at-startup "swaybg -i ~/Pictures/Wallpapers/wallpaper.jpg -m fill"

// Add this line: spawn-at-startup "qs" "-c" "noctalia-shell"

The layer-rule blocks for noctalia-wallpaper and noctalia-overview in section 5 must remain in place — they tell Niri to place the Noctalia wallpaper layer behind the backdrop.

First-time setup

Test Noctalia from a terminal inside a running Niri session:

qs -c noctalia-shell

Noctalia will display its setup wizard on first run. Follow the prompts to choose your wallpaper and color scheme. Config files are stored at ~/.config/noctalia/.

Dynamic theming with matugen

To manually regenerate the color scheme from a wallpaper:

matugen image ~/Pictures/Wallpapers/wallpaper.jpg

7. Showing Keybinds

Method 1 — Built-in hotkey overlay (recommended)

Niri has a native hotkey overlay that shows all your current bindings on screen. It is already bound in config.kdl above:

Mod+Shift+Slash hotkey-overlay-title="Show This Keybind Overlay" {
    show-hotkey-overlay;
}

Press Super+Shift+/ (Super+?) at any time to display the overlay. Press any key or click to dismiss it.

Every bind that has a hotkey-overlay-title="..." property will show that description next to the key in the overlay. Binds without a title use the action name. The full config in section 5 already includes descriptive titles for all the main bindings.

Control the overlay’s appearance in config.kdl:

hotkey-overlay {
    skip-at-startup          // do not show on first Niri launch
    // hide-not-bound        // uncomment to only show actions with a keybind
}

You can also trigger the overlay from the command line (useful for scripting):

niri msg action show-hotkey-overlay

Method 2 — Noctalia keybind cheatsheet plugin

If you are using Noctalia Shell, it provides a plugin that parses your Niri config and shows a searchable, categorized keybind list. You can organize bindings into sections using comment tags:

// In config.kdl — add category comments above bind groups:
// #"Applications"
Mod+Return hotkey-overlay-title="Open Terminal" { spawn "foot"; }
Mod+D hotkey-overlay-title="App Launcher" { spawn "fuzzel"; }

// #"Windows" Mod+Q hotkey-overlay-title="Close Window" { close-window; }

Trigger the Noctalia cheatsheet with:

Mod+F1 hotkey-overlay-title="Keybind Cheatsheet" {
    spawn-sh "qs -c noctalia-shell ipc call plugin:keybind-cheatsheet toggle";
}

8. Setting Default Applications

Create mimeapps.list

nano ~/.config/mimeapps.list
[Default Applications]
# Browser
x-scheme-handler/http=firefox.desktop
x-scheme-handler/https=firefox.desktop
text/html=firefox.desktop
application/xhtml+xml=firefox.desktop

# File manager inode/directory=thunar.desktop

# Text editor text/plain=nvim.desktop

# Images image/jpeg=imv.desktop image/png=imv.desktop image/gif=imv.desktop image/webp=imv.desktop image/svg+xml=imv.desktop

# Video video/mp4=mpv.desktop video/x-matroska=mpv.desktop video/webm=mpv.desktop video/avi=mpv.desktop

# Audio audio/mpeg=mpv.desktop audio/flac=mpv.desktop audio/ogg=mpv.desktop

# Documents application/pdf=org.pwmt.zathura.desktop

Set defaults with xdg-mime

xdg-mime default firefox.desktop x-scheme-handler/http
xdg-mime default firefox.desktop x-scheme-handler/https
xdg-mime default thunar.desktop inode/directory
xdg-mime default imv.desktop image/jpeg
xdg-mime default imv.desktop image/png
xdg-mime default mpv.desktop video/mp4

# Verify any entry xdg-mime query default image/jpeg

handlr — better xdg-open (AUR)

yay -S handlr-bin
handlr set .pdf zathura.desktop
handlr set .png imv.desktop
handlr set x-scheme-handler/https firefox.desktop
handlr list

9. Enable Services

# PipeWire (if not already done in step 2)
systemctl --user enable --now pipewire pipewire-pulse wireplumber

# Verify audio systemctl --user status pipewire pipewire-pulse wireplumber

# Noctalia (if installed) systemctl --user enable noctalia-shell

10. Starting Niri

From a TTY (recommended)

Always use niri-session rather than bare niri for production use. niri-session imports environment variables into systemd and D-Bus so that portals, screen sharing, and services work correctly.

niri-session

Auto-start on TTY login

Add to ~/.bash_profile (bash) or ~/.zprofile (zsh):

if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
    exec niri-session
fi

From a display manager

If SDDM, GDM, or another display manager is installed, log out and select Niri from the session menu.

Test without committing (nested mode)

Run Niri as a window inside an existing session to test config changes safely:

niri

Validate config before starting

niri validate

Any KDL syntax errors are reported with line numbers. Fix them before starting Niri to avoid a blank screen.

11. NVIDIA Troubleshooting

| Symptom | Fix | |—|—| | Blank screen on start | Comment out __GLX_VENDOR_LIBRARY_NAME "nvidia" in the environment {} block | | Very high VRAM usage | Confirm the VRAM fix JSON in /etc/nvidia/nvidia-application-profiles-rc.d/ is in place | | Screen freezes after suspend | Confirm NVreg_PreserveVideoMemoryAllocations=1 is in /etc/modprobe.d/nvidia.conf | | Screen stays black after resume | Add after-sleep handler to swayidle: after-sleep "niri msg action power-on-monitors" | | Wrong render device on hybrid Intel+NVIDIA | Add to config.kdl: debug { render-drm-device "/dev/dri/renderD128"; } — try renderD129 if that fails | | Electron apps not Wayland native | Confirm ELECTRON_OZONE_PLATFORM_HINT "auto" is in the environment {} block | | XWayland apps not working | Confirm xwayland-satellite is installed and started via spawn-at-startup "xwayland-satellite" | | Portals not working (no screen share) | Confirm both xdg-desktop-portal-gnome and xdg-desktop-portal-gtk are installed; check spawn-at-startup D-Bus propagation lines are present |

Verify environment variables inside Niri

Environment variables set in the environment {} block only exist in processes spawned by Niri. Open a terminal inside a running Niri session to check them — they will be empty in a bare TTY.
# Run from inside foot or alacritty within a running Niri session
echo $GBM_BACKEND              # nvidia-drm
echo $LIBVA_DRIVER_NAME        # nvidia
echo $XDG_SESSION_TYPE         # wayland
echo $XDG_CURRENT_DESKTOP      # niri
niri msg version                # shows running Niri version
niri msg outputs                # shows connected monitors

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top