Setting up a streaming gaming Ubuntu PC for moonlight #

I’ve been working on building a new streaming gaming PC (that ordeal I will save for a future blog post), but in the process I had some difficulties with getting moonlight set up just the way I like it. So I figured these might be helpful to others.

My goal is to have a PC that I use exclusively for streaming games via sunshine. Sunshine is the replacement for Nvidia game streaming that was deprecated, and work as a complement to the streaming client moonlight. It allows for the streaming of video and audio to a client, which in turn streams controls (keyboard and / or a controller) back to the server.

When all is said and done, I want what is effectively a box in my closet with only two things attached: a power cable, and an ethernet cable (for a low-latency wired connection to my network). I do not want dangling mice, keyboards or monitors. Just a box that connects to the internet, and is available for me to stream from.

To accomplish this, I needed a few things:

  1. A way to have a virtual display even if a physical monitor isn’t plugged in.
  2. A way to login as a user right away (since sunshine needs a valid user).
  3. A way to have sunshine available when the machine boots.
  4. A way to wake the machine after it suspends

Attaching a virtual display #

This was relatively easy!

You can buy a dummy plug that you just plug into the GPU. When you’ve got your PC set up, just replace your actual monitor with that.

Logging in right away #

This one just requires careful setup:

  1. setup autologin in your operating system (varies by distro).
  2. do not use disk encryption.

(2) is the major gotcha: if you add disk encryption it’ll ask for your password every time your computer starts up, which means plugging in a keyboard every time. you could just leave a keyboard by your computer for this purpose, but I’ve found I do have to restart my computer from time to time, and making bringing it back up as easy as pressing a button is a nice usability improvement.

Start sunshine when the machine boots #

This was pretty hard for me. Normally, this is a matter of installing the sunshine .deb from the github releases, but in my case I had to use Ubuntu 25.05 for a newer kernel version that supports my AMD GPU. Only LTS release are supported for sunshine.

For a non-lts release, I found that using the .appimage worked the best. This unfortunately didn’t work for me without root, so I had to run sunshine as sudo:

sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native /usr/bin/sunshine

(I moved the appimage to /usr/bin/sunshine).

I put this in a script, which I then added as a startup application:

#!/usr/bin/env bash
# I had to add a sleep to let the graphical interface completely come up.
# otherwise I would see a black screen.
sleep 10
exec sudo -i PULSE_SERVER=unix:/run/user/$(id -u $whoami)/pulse/native /usr/bin/sunshine

This works, but still has some wonkiness:

  • steam can’t be launched via moonlight because it tries to start it as root.

A way to wake the machine, after it suspends #

Now you probably don’t want your machine on all the time - instead, you’d want it to suspend after a reasonable idle time frame, and have the ability to turn it one when you need it.

I tried a few approach, none of which worked or were reliable (I think something else was resetting my network configuration):

Ultimately I landed on the following:

# /lib/systemd/system/wol@.service
[Unit]
Description=Wake-on-lan for %i
# This means run after the network is online, as well
# as after suspension.
After=network-online.target suspend.target

[Service]
Type=oneshot
# something else in my OP keeps setting the WOL settings on the device.
# adding this sleep gave whatever time to configure it's settings, so I could override them.
ExecStartPre=/usr/bin/sleep 10
ExecStart=/sbin/ethtool -s %i wol g

[Install]
# if we run network-online and suspend.target, run this too.
WantedBy=network-online.target suspend.target

Installed by:

systemctl enable wol@${ethid}

Where ${ethid} is the interface id you can get from nmcli.

Conclusion #

And that’s it! Most of it was troubleshooting systemd units. My takeaways are:

  • try to use systemd units as much as possible. It’s an extremely powerful system and enables you to start your process with the right sequencing and situations.
  • try to use LTS releases of Ubuntu if at all possible. Moonlight installation has been tricky, and I’m sure other packages only support LTS. I’m looking forward to upgrading to 2026.04 precisely for this benefit.

Why linux? Why ubuntu? #

Although not for everyone, I like to use Linux for a few reasons:

  1. Linux distributions don’t to forced updates, thereby allowing gaming uninterrupted by some malware update.
  2. Windows has a ton of bloatware and ads.
  3. Linux is “free” - it doesn’t cost a cent to run it, and distros often work for years.
  4. With the work done on wine and proton, Windows games run extremely smooth on Linux now.

For Ubuntu, I would go with bazzite for a pure gaming PC, but as this computer will be the most powerful one I have, I wanted it to have the option to be more general purpose in case I get the itch to do some real software development on it (maybe ML or some CPU emulation project).