Sunshine/Moonlight on Linux: Stream Your KDE Desktop to a TV with Low Latency

Gaming setup with backlit keyboard — a stand-in for low-latency streaming

I spent a few hours trying to get my KDE desktop onto the living room TV before I found something that actually worked. The obvious first idea, streaming through the Chromecast Default Media Receiver like a video file, never got below a few seconds of delay no matter how much I tuned bitrate and resolution. Turns out that's not a tuning problem. Google's Cast Default Media Receiver is built for buffered video, not for mirroring, and there's a hard floor you can't tune your way past.

What actually got me there was Sunshine and Moonlight. They're open-source, built on the same idea as Nvidia's GameStream, and they're a genuinely different technology from screen mirroring: instead of pushing frames through a media-player protocol, Sunshine hosts a real streaming session and Moonlight decodes it on the other end. I'm not going to pretend this is a scientific benchmark, but streaming to an Android TV projector in my living room, the desktop felt responsive enough to actually use, not just watch. Well under a second, by feel.

Everything below is tested on openSUSE Tumbleweed, KDE Plasma 6, Wayland, an AMD RX 6650 XT, streaming to a JMGO N1S Pro. If you're on a different distro or GPU, the concepts hold but some commands won't.

Casting isn't one thing

People say "cast my screen" and mean two different technologies.

Miracast mirrors a display over Wi-Fi Direct. Where it's supported cleanly it needs no extra software on your PC, but Linux driver support is spotty, and it was never built for high frame rates or tight audio sync.

Sunshine and Moonlight work differently. Sunshine runs on your PC and hosts a streaming session — encoding video, audio, and input and sending it over a dedicated protocol instead of through your desktop's mirroring path. Moonlight decodes it on the receiving end. That's the technology this guide is about, because it's the one built for actually using a remote desktop, not just watching it.

Miracast or Sunshine/Moonlight?

MiracastSunshine/Moonlight
LatencyMirroring-grade, hardware-dependentSub-second by feel in my test
Good for gamingNot reallyYes
ClientMiracast/WFD receiverAndroid/Google TV with app support
Setup effortLow, where it worksA real install and pairing process
Best forQuick mirroring, presentationsGaming, video, actually driving a remote desktop

If you just need to throw something on screen for five minutes and Miracast works on your hardware, use it. If you want a desktop you can operate from the couch, keep reading.

How it fits together

KDE desktop (Sunshine host)
        │  regular LAN, no WiFi Direct needed
        ▼
Moonlight client (TV / Android TV box)

Both devices need to be on the same network. On KDE/Wayland, Sunshine captures the desktop through xdg-desktop-portal and PipeWire — that's the path I got working, because KWin doesn't support wlr-export-dmabuf, the protocol some other compositors use for a more direct route. I didn't test whether direct KMS capture works on a native package build without going through the portal, so treat capture = portal as the setting I know works, not necessarily the only one that could.

Living room TV — the typical target device for desktop streaming

Before you start

  • KDE Plasma 6 on Wayland. I haven't tried this on X11 or older Plasma.
  • A distro with Sunshine packaged, or Flathub if yours doesn't have it.
  • An Android/Google TV device with Moonlight installed from its app store. A "Chromecast built-in" TV without app support won't cut it.
  • Both devices on the same LAN. Guest networks and AP-isolated Wi-Fi will block discovery.
  • Hardware video encoding helps a lot. Software encoding works but you'll feel the difference.
  • Sunshine listens on your local network by default. Don't forward its ports to the internet unless you actually mean to and know what that exposes.

Setting it up

1. Install Sunshine

On openSUSE Tumbleweed:

sudo zypper addrepo https://download.opensuse.org/repositories/games:/tools/openSUSE_Tumbleweed/games:tools.repo
sudo zypper install sunshine sunshine-firewalld

No AppImage or Flatpak sandboxing needed for the native package. Other distros: check your own repos first, and Sunshine is on Flathub as dev.lizardbyte.app.Sunshine if there's nothing native. sunshine-firewalld opens the ports you'll need automatically.

2. First run

Start Sunshine from your app menu or run sunshine in a terminal, then open https://localhost:47990. Your browser will complain about the certificate — it's self-signed, that's expected, accept it. First time in, you'll create a username and password for the web UI. Write them down.

3. Set the capture backend

In the web UI's Configuration tab, set capture to portal. It lives in ~/.config/sunshine/sunshine.conf too, as capture = portal, if you'd rather edit the file. Save and restart Sunshine if it asks.

4. Install Moonlight

On the TV/box: install from the app store. For a desktop client, moonlight-stream.org has builds.

5. Pair them — the direction trips people up

Open Moonlight on the client and add your PC. It should find it automatically on the LAN; if not, add it by IP. Moonlight will then ask you for a PIN — that PIN shows up on the client, and you type it into Sunshine's web UI, under the PIN page in the nav bar. It's backwards from what you'd guess.

6. First stream

KDE's portal will pop up a permission dialog asking which screen to share. That's the screen-capture consent step, separate from input permissions, which come later. Approve it. If you've got multiple monitors, this is where you pick one.

7. Check it's actually working, not just running

Video and audio should show up within a couple seconds. Check Sunshine's logs for which encoder is active — you want your GPU's hardware encoder name there, not a software fallback, because that's the difference between "responsive" and "why is this laggy." Keyboard, mouse, and controller from the client should control the host. If a controller doesn't respond, that's a separate permission path (usually uinput device access) — don't assume the screen-capture prompt covered it, because it didn't for me either the first time.

One gap I haven't closed yet: this runs as a manually started process, not a systemd service, so it doesn't survive a reboot. A user systemd unit would fix that. I just haven't set it up.

What it actually felt like

Streaming to the JMGO N1S Pro over a normal home network, the desktop felt responsive enough to operate, not just watch, and audio stayed in sync. That's a real impression from real use, not a number from a repeatable benchmark — I didn't log resolution, bitrate, or a measured round-trip time. If you need hard numbers for something latency-critical, measure your own setup.

Where Hermes might be worth a look

If vanilla Sunshine hits a specific wall on your Linux/Wayland/AMD setup, whether that's the portal capture step or a VAAPI driver-path mismatch, there's Hermes: a fork of Apollo, which is itself a fork of Sunshine. It solves both problems at a lower level, with its own kernel module for direct capture instead of going through the desktop portal. It's actively maintained, not the dead side project it might look like from a glance at GitHub's inherited fork history. Its docs are written for Arch and CachyOS, though, so on openSUSE you're building from source, not installing a package — a real step up in effort from the vanilla Sunshine install above.

Here's the part that made me put it back on the "advanced only" shelf: that kernel module has to be manually trusted through Secure Boot's Machine Owner Key enrollment, a one-time step that needs physical keyboard and monitor access at boot. I built and loaded it myself, and it flatly refused to load until I enrolled the key through the physical MOK Manager screen — no way around it, even with proper distro packaging. Most desktop distros ship Secure Boot on by default, so this isn't some rare edge case you'll dodge.

Try vanilla Sunshine first. Only look at Hermes if you hit a wall it's specifically known to fix.

Troubleshooting

  • No permission dialog when you start streaming: check xdg-desktop-portal and the KDE portal backend are actually running, and that capture = portal took effect in the config.
  • Black screen, audio's fine: almost always a capture backend mismatch — confirm the Configuration tab setting stuck and Sunshine restarted after you changed it.
  • No audio on the client: check Sunshine's audio device selection; your system's default sink can shift after a reboot.
  • Controller doesn't respond: separate permission path from screen capture, check uinput device access.
  • Choppy playback: drop resolution/bitrate first to figure out if it's network or encoding.
  • High latency on a decent network: check the active encoder in the logs — make sure it's not silently falling back to software.
  • Host not showing up: confirm both devices share a LAN, not a guest network or isolated Wi-Fi, and try adding it by IP directly.

So which one

Need to mirror something quickly and your hardware does Miracast cleanly? Use Miracast. Want a desktop on your TV you can actually drive, for gaming or anything interactive? Sunshine and Moonlight, following the walkthrough above. Hit a specific wall with vanilla Sunshine and you're comfortable enrolling Secure Boot keys? Look at Hermes, not as your first move.

If you landed here after Chromecast let you down, this isn't a workaround for that. It's a different, more responsive way to do the whole thing, and it costs you one real setup session to get there.

← Back to KCast

Logo githubMy Github
mastodon logoFollow me
Logo hire meHire me
Logo EmailEmail