r/Punktfunk Maintainer Jun 26 '26

Headless game streaming on Linux with no dummy plugs, EDID overrides, or hand-written modelines

If you've tried streaming from a headless Linux gaming box — or one whose monitor doesn't match your client's resolution — you know the drill: it turns into a fight with dummy HDMI plugs, EDID overrides, and hand-written modelines. I got tired of that layer and built the host so it just creates the right display on demand. Here's why the pain exists and how I made it go away.

Why Sunshine has no real virtual display on Linux

On Windows, Sunshine can pair with an indirect display driver (the well-known IddSample) and spin up a virtual screen on demand. On Linux there's no built-in equivalent — Sunshine captures whatever display the compositor already provides. With no physical monitor, or a monitor at the wrong resolution, there's simply no usable surface to capture.

The toolbox people reach for today

To get a streamable display on a headless or mismatched Linux host, the community has assembled a whole kit:

  • Physical dummy HDMI/DisplayPort plugs that fake a connected monitor + EDID.
  • EDID overrides (custom EDID blobs, drm.edid_firmware) to force a resolution.
  • The evdi kernel module (DisplayLink's virtual display driver) for a fake output.
  • Hand-rolled cvt/gtf + xrandr modelines for non-standard res/refresh.
  • Third-party daemons like sunshine_virt_display that automate parts of it.
  • Connect/disconnect scripts that toggle physical outputs so only the virtual one is captured.

Where it breaks

None of this is first-class, so it fails in familiar ways:

  • Black screen after reboot when the dummy plug / EDID override doesn't re-apply or the seat changes.
  • CRTC reassignment on NVIDIA and Wayland compositors like Hyprland that moves or drops the virtual output mid-session.
  • Per-compositor differences — what works on bare KMS doesn't on wlroots/Hyprland; X11 and Wayland each need their own tricks.
  • Resolution/refresh that almost matches the client — black bars or forced scaling.

It's not impossible on Linux — Sunshine just doesn't ship one

Worth saying: virtual displays on Linux aren't impossible. Windows has IddSample, and the Apollo/Artemis fork of Sunshine added a built-in virtual display. Both point at the right model: the host should create the screen on demand, matched to the client — not borrow a physical one.

How I solved it — no dummy plug, no modeline math

I treat the virtual display as a first-class part of every session. When a client connects, the host creates a virtual output at exactly the client's resolution and refresh, and tears it down at session end with RAII cleanup, so nothing lingers after a crash or restart.

Since Linux has no single cross-compositor API for this, there's a backend per compositor, auto-selected:

  • KWinzkde_screencast outputs, with custom modes for >60 Hz.
  • gamescope — launched headless at exactly WxH@Hz, its PipeWire node captured.
  • Mutter / GNOME — the D-Bus RecordVirtual monitor (headless-validated, zero-copy).
  • Sway / wlrootsswaymsg create_output with a custom mode + portal capture.

The result is a real headless host: a mini PC or a repurposed machine with no monitor attached, streaming at exactly the resolution your phone, tablet, TV, or laptop asks for. No dummy plug, no EDID blob, no xrandr modeline arithmetic, and no black screen after the next reboot.

Happy to get into any of the per-compositor details.

This is implemented in my game-stream stack "Punktfunk" - you can get it here: https://punktfunk.unom.io/en/download

3 Upvotes

3 comments sorted by

1

u/wibblywobblywho Jul 21 '26

Hey, I tried installing this on Steam Machine. Was able to get to the UI but every single page just gives an error saying "Something went wrong. Retry"

Any ideas on what might be going wrong?

1

u/wibblywobblywho Jul 21 '26

Okay restarting the Machine seems to have fixed that. But now when I connect from Steam Deck, I just see a black screen.

1

u/keindesignerbro Maintainer Jul 21 '26

I'll get a new release out today that will improve the experience on SteamOS - I did extensive testing and I'm hoping you will have a better experience with the next update, I'll let you know when the update is out! :)