Skip to content

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸŒ’ Sunveil

On-demand headless virtual display for Sunshine on CachyOS (KDE Plasma 6 / Wayland / NVIDIA).

Stream your PC with Moonlight / Artemis at your client's native resolution β€” phone, tablet, laptop, TV β€” with the host's physical monitors turned off for the duration of the stream, then restored automatically when you disconnect.

No dummy HDMI plug. No always-on fake display. No Windows. Pure software, built for and tested on CachyOS + Plasma 6 Wayland + NVIDIA proprietary drivers.

Sunveil demo β€” a phone connects, a virtual display is created at its native resolution, the physical monitors turn off, and everything is restored on disconnect

The clip shows the real hook output: a phone connects at 1080Γ—2340@90, the virtual display is created at that exact resolution, the physical monitors are disabled, and on disconnect everything is restored β€” primary monitor and all.


What it does

When a Moonlight client connects, Sunveil:

  1. Creates a virtual monitor at the client's exact resolution and refresh rate (e.g. your phone gets 1080Γ—2340@90, your laptop gets 2560Γ—1440@144).
  2. Turns off your physical monitors so the stream is an exclusive, private headless display (optional β€” see Coexist mode).
  3. Points Sunshine's KWin capture at the virtual display and streams it.
  4. On disconnect, restores everything β€” physical monitors back on, virtual display destroyed, primary monitor and layout exactly as they were.

It's driven entirely by Sunshine's global_prep_cmd hooks, so there's nothing running when you're not streaming.

Why not just use a dummy plug or Apollo?

  • Dummy HDMI plugs work but are a fixed resolution, always present, and cost money/ports. Sunveil is dynamic and leaves no trace when idle.
  • Apollo's virtual display is Windows-only (it relies on SudoVDA). On Linux it can't create a virtual display. Sunveil fills that gap for CachyOS.
  • Hermes (an Apollo-for-Linux fork) is a great heavier alternative if you want a purpose-built host; Sunveil instead enhances the Sunshine you already run, in ~15 minutes, with stock packages.

Requirements

OS CachyOS / Arch (uses pacman)
Desktop KDE Plasma 6 on Wayland
GPU Any Sunshine-supported GPU. Developed on NVIDIA (proprietary/open).
Sunshine Already installed and working (systemctl --user status app-dev.lizardbyte.app.Sunshine.service)
Packages krfb, kscreen β€” the installer adds these for you

X11 is not supported. The virtual display is created at the KWin/Wayland compositor level. If echo $XDG_SESSION_TYPE prints x11, log into a "Plasma (Wayland)" session first.


Install

git clone https://github.com/ImStillBlue/sunshine-virtual-display.git
cd sunshine-virtual-display
./install.sh

That's it. The installer is idempotent and safe on an existing Sunshine setup β€” it backs up your sunshine.conf, merges only the keys it needs (preserving any prep commands you already have), installs the hooks, and adds a systemd fix for the boot-time click bug (see Troubleshooting).

Then just connect from Moonlight and start streaming.

Options

./install.sh --coexist      # keep physical monitors ON (extend, not replace)
./install.sh --no-restart   # don't restart Sunshine at the end
./install.sh --yes          # non-interactive

Uninstall

./uninstall.sh

Restores your Sunshine config from the backup and removes everything Sunveil added. (Leaves the krfb package and any autologin you set up β€” those are yours to keep or remove.)


Modes

Set in ~/.config/sunshine/hooks/sunveil.conf (or via --coexist at install):

DISABLE_PHYSICAL Behaviour
true (default) Headless β€” physical monitors off while streaming, restored on disconnect.
false Coexist β€” virtual display is an extra screen; your real monitors keep showing your desktop. Great for streaming to a second device while someone uses the PC.

Changes take effect on the next stream β€” no restart needed.


Truly headless: stream a PC that was never logged in

Sunshine runs as a user service, so it only starts after you log into a Plasma session. To stream a freshly-booted machine (e.g. a headless box in a closet), enable autologin so Plasma comes up on boot:

# Plasma 6 uses SDDM ("plasmalogin"). Create an autologin drop-in:
printf '[Autologin]\nUser=%s\nSession=plasma.desktop\nRelogin=false\n' "$USER" \
  | sudo tee /etc/sddm.conf.d/autologin.conf
  • Relogin=false β€” autologin only at boot; you can still log out normally.
  • Relogin=true β€” re-login even after logout/crash (pure appliance mode).

Note: loginctl enable-linger does not help here β€” linger starts user daemons at boot but never starts a graphical Plasma session, which Sunshine needs to capture. Autologin is the right tool.

See docs/AUTOLOGIN.md for the security tradeoffs and a KWallet note.


Troubleshooting

πŸ–±οΈ Cursor moves but clicks do nothing

The single most common issue on autologin/fast-boot systems. Sunshine created its virtual input device before KWin finished starting, so pointer motion bound but button capabilities didn't.

Sunveil installs a systemd override that fixes this by making Sunshine wait for KWin before it starts. If you still hit it (e.g. after a manual change):

systemctl --user restart app-dev.lizardbyte.app.Sunshine.service

…once the desktop is fully up. See docs/TROUBLESHOOTING.md for the full explanation and how we diagnosed it.

The stream is black / Sunshine can't find the display

Sunshine's default capture (kms) cannot see compositor-level virtual monitors. Sunveil sets capture = kwin for you. Confirm it's set:

grep -E 'capture|output_name' ~/.config/sunshine/hooks/../sunshine.conf
# capture = kwin
# output_name = Virtual-sunshine-vm

Nothing happens when I connect

Watch the hook log live while you connect:

tail -f ~/.config/sunshine/hooks/hook.log

You should see client requested WxH@fps, virtual output: Virtual-sunshine-vm, and (in headless mode) disabled physical: …. If it says virtual output never appeared, krfb-virtualmonitor failed β€” check that krfb is installed and you're on Wayland.

krfb-virtualmonitor: Failed to register with host portal

Harmless. It's a cosmetic app-id warning from krfb; the virtual monitor still works. Ignore it.

More in docs/TROUBLESHOOTING.md.


How it works (for the curious)

Moonlight client connects
        β”‚
        β–Ό
Sunshine runs global_prep_cmd "do"  ──►  hooks/stream-start.sh
        β”‚                                   β€’ reads SUNSHINE_CLIENT_WIDTH/HEIGHT/FPS
        β”‚                                   β€’ krfb-virtualmonitor --resolution WxH
        β”‚                                   β€’ kscreen-doctor: add custom mode, set it
        β”‚                                   β€’ kscreen-doctor: disable physical outputs
        β–Ό
Sunshine captures output_name = Virtual-sunshine-vm  (capture = kwin)
        β”‚
        β–Ό
… you stream …
        β”‚
Moonlight disconnects
        β–Ό
Sunshine runs global_prep_cmd "undo"  ──►  hooks/stream-end.sh
                                            β€’ re-enable physical outputs
                                            β€’ restore original primary
                                            β€’ kill krfb-virtualmonitor

Files installed:

~/.config/sunshine/hooks/stream-start.sh     # the "do" hook
~/.config/sunshine/hooks/stream-end.sh       # the "undo" hook
~/.config/sunshine/hooks/sunveil.conf        # your tunables
~/.config/sunshine/hooks/hook.log            # per-stream debug log
~/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service.d/sunveil.conf
~/.config/sunshine/sunshine.conf             # merged: capture, output_name, global_prep_cmd
                                             # (original saved as sunshine.conf.sunveil-bak.*)

Related projects

The game-streaming ecosystem Sunveil plugs into:

Project What it is
Sunshine The self-hosted stream host Sunveil enhances.
Moonlight (GitHub) The original open-source streaming client, for basically every platform.
Apollo A Sunshine fork with a built-in virtual display β€” but Windows-only (SudoVDA). The inspiration for doing this on Linux.
Artemis Apollo's companion Android client (a moonlight-android fork). Works great as the client for a Sunveil host.
Hermes An Apollo-for-Linux host fork with its own virtual-display driver β€” a heavier alternative if you'd rather replace Sunshine than enhance it.
krfb KDE app that ships krfb-virtualmonitor, the tool that actually creates the virtual display.

Credits & license

Built on the shoulders of Sunshine, KDE's krfb-virtualmonitor, and kscreen-doctor. The virtual-monitor approach was inspired by community write-ups on running Sunshine headless on Plasma 6 Wayland, and by Apollo's native virtual-display feature on Windows.

MIT β€” see LICENSE.

Contributions welcome, especially test reports from other CachyOS/Arch + Plasma 6 configurations. See CONTRIBUTING.md.

About

On-demand headless virtual display for Sunshine on CachyOS (KDE Plasma 6 Wayland). Streams Moonlight/Artemis at the client's native resolution with host monitors off, restored on disconnect.

Topics

Resources

Contributing

Stars

11 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages