Virtual Display on KDE Wayland: Krfb-Virtualmonitor + Sunshine Streaming

My setup

  • CachyOS (Arch-based)
  • KDE Plasma 6 + Wayland
  • NVIDIA RTX 2070 Mobile, proprietary driver 570
  • Sunshine v2025.x

Steps

1. Install dependencies

sudo pacman -S krfb kscreen

krfb provides the krfb-virtualmonitor command, and kscreen provides kscreen-doctor for adjusting resolution and refresh rate.

2. Create the virtual display

krfb-virtualmonitor --resolution 2560x1440 --name sunshine-vm --password pass --port 5905 &

Parameter notes:

  • --resolution: Initial resolution. Give it a large value (e.g., 2560x1440 or 3840x2160) — you can switch to a specific resolution later with kscreen-doctor
  • --name: Pick whatever you like. You’ll reference this in kscreen-doctor commands
  • --password / --port: VNC password and port. You don’t need VNC access for Moonlight, but these are required arguments

After running, open System Settings → Display & Monitor — you should see the new virtual display.

Verify:

kscreen-doctor -o | grep -A5 Virtual

3. Configure Sunshine

This is the critical step: Sunshine’s default capture mode is kms, which can’t see krfb-virtualmonitor outputs (those exist at the Wayland compositor level, not the DRM/KMS level). You need to switch to kwin mode.

Sunshine Web UI → Configuration → Advanced → Force Capture Method → select kwin.

Restart Sunshine:

systemctl --user restart sunshine

4. Setting refresh rate

krfb-virtualmonitor has no --refresh parameter — it defaults to 60 Hz. To change it:

# Unit is mHz: 120 Hz = 120000
kscreen-doctor output.Virtual-sunshine-vm.addCustomMode.1920.1080.120000.full

# Apply
kscreen-doctor output.Virtual-sunshine-vm.mode.1920x1080@120

Note the different formats: addCustomMode takes dots (1920.1080.120000), while mode uses the conventional format (1920x1080@120). Don’t mix them up.

Verify:

kscreen-doctor -o | grep -A10 Virtual

You should see the * marker next to the current mode and refresh rate.

5. Optional: manage the virtual display with systemd

If you don’t want to manually start the virtual display every time, wrap it in a user service for autostart.

# ~/.config/systemd/user/krfb-virtualmonitor.service
[Unit]
Description=Virtual display for Sunshine streaming
After=graphical-session.target
PartOf=graphical-session.target

[Service]
Type=simple
ExecStart=/usr/bin/krfb-virtualmonitor --resolution 2560x1440 --name sunshine-vm --password pass --port 5905
ExecStartPost=/bin/sh -c 'sleep 3 && /usr/bin/kscreen-doctor output.Virtual-sunshine-vm.addCustomMode.1920.1080.120000.full && /usr/bin/kscreen-doctor output.Virtual-sunshine-vm.mode.1920x1080@120'
Restart=on-failure
RestartSec=5

[Install]
WantedBy=graphical-session.target
systemctl --user daemon-reload
systemctl --user enable --now krfb-virtualmonitor.service

This must be a user service. A system service doesn’t have access to $WAYLAND_DISPLAY and $XDG_RUNTIME_DIR, so krfb-virtualmonitor can’t connect to KWin.

The ExecStartPost command does three things: waits 3 seconds for KDE to register the virtual display → registers a custom mode (addCustomMode) → switches to it (.mode.). addCustomMode only registers — it doesn’t switch. You always need .mode. afterward.

To also set the display scale:

ExecStartPost=/bin/sh -c 'sleep 3 && /usr/bin/kscreen-doctor output.Virtual-sunshine-vm.addCustomMode.2560.1440.120000.full && /usr/bin/kscreen-doctor output.Virtual-sunshine-vm.mode.2560x1440@120 && /usr/bin/kscreen-doctor output.Virtual-sunshine-vm.scale.1.5'

Keep --resolution, addCustomMode, and .mode. values consistent. Adjust scale as needed (1.5 = 150%).

Fractional scaling: For non-integer values like 1.5, enable “Allow fractional scaling” in System Settings → Display & Monitor first, or set XwaylandScaleOverride=150 in ~/.config/kwinrc and restart kwin.

If you’d rather not keep the virtual display running all the time, you can tie it to Sunshine’s service lifecycle for on-demand start/stop:

# ~/.config/systemd/user/sunshine.service.d/override.conf
[Unit]
Wants=krfb-virtualmonitor.service
After=krfb-virtualmonitor.service

This pulls in the virtual display when Sunshine starts and stops it when Sunshine exits.

Display switching

Moonlight has a built-in shortcut: Shift + Ctrl + Alt + F1 ~ F12 to switch between virtual desktops/displays.

Connect via Moonlight, then press this combo to toggle between your physical display and the virtual one. No need for do/undo scripts that disable physical monitors — just switch. Whatever is on the physical screen doesn’t affect the stream.

If you have three or more displays (e.g., laptop panel + external monitor + virtual display), F1/F2/F3 map to different outputs.

References