# 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

```bash
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

```bash
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:

```bash
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:

```bash
systemctl --user restart sunshine
```

### 4. Setting refresh rate

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

```bash
# 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:

```bash
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.

```ini
# ~/.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
```

```bash
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:

```ini
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:

```ini
# ~/.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

- [Reddit: Sunshine on KDE Wayland with krfb-virtualmonitor](https://www.reddit.com/r/MoonlightStreaming/comments/1tg1dnc/guide_sunshine_on_kde_wayland_virtual_display/)
- [KDE Discuss: How to create a virtual monitor](https://discuss.kde.org/t/how-to-create-a-virtual-monitor-display/2725)
- [krfb-virtualmonitor man page](https://linuxcommandlibrary.com/man/krfb-virtualmonitor)


---

> Author: Nite  
> URL: https://www.nite07.com/en/posts/kde-virtual-display-sunshine/  

