// 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 upstreamquickshellorquickshell-gitpackage installed, it conflicts withnoctalia-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
// categories
// recent posts