How to set up Headless Sunshine on Ubuntu server 22.04 with an Nvidia gpu

This is a guide on setting up a headless Sunshine game streaming server on Ubuntu server 22.04 with no physical display attached. For this guide you will need root or have sudo permissions.

First lets install the prerequisite packages.

  1. Install the ubuntu desktop meta package using

sudo apt-get install ubuntu-desktop

  1. Install the Nvidia driver and cuda tool kit using the instructions at this link.
  2. Download the Sunshine Ubuntu 22.04 release from here
  3. install it with this command

sudo apt install -f ./sunshine-ubuntu-22.04-amd64.deb

  1. reboot your system

Patching the Nvidia driver
Download the Nvidia driver patcher from here to patch in Nvidia frame buffer copy.

cd nvidia-patch
./patch-fbc.sh

Next lets configure the desktop environment.

  1. Start be editing the gdm config file to disable wayland and autolog in the user you want to access remotely.

vi /etc/gdm3/custom.conf
uncomment the WaylandEnable=false line
as well as these two lines. Replace user with the username of who you want to auto login
AutomaticLoginEnable = true
AutomaticLogin = user

  1. Switch to the home of the user you set to autologin and edit the pipewire config file to unload bluetooth driver, if you don’t do this pipewire will fail to autostart and sunshine will crash when you try to connect as it will be unable to create an audio sink

vi ~/.config/pulse/default.pa to include

###unload driver modules for Bluetooth hardware
.ifexists module-bluetooth-policy.so
unload-module module-bluetooth-policy
.endif
.ifexists module-bluetooth-discover.so
unload-module module-bluetooth-discover
.endif

  1. Create an edid file to fake a connected display. This file should be in the user you set to autologin home directory.

A sample edid that supports up to 1080p60can be downloaded from here

  1. Setting up an Xorg config file
    run nvidia-xconfig to create an Xorg config file

nvidia-xconfig

then edit it with

vi /etc/X11/xorg.conf

Replace the screen section with this, where edid path is the full path to the edid file.

Section “Screen”
Identifier “Screen0”
Device “Device0”
Monitor “Monitor0”
DefaultDepth 24
Option “AllowEmptyInitialConfiguration” “True”
Option “UseDisplayDevice” “DP-0”
Option “CustomEDID” “DP-0:Edid Path
Option “ConnectedMonitor” “DP-0”
SubSection “Display”
Depth 24
EndSubSection
EndSection

Next create a udev rule to allow sunshine to create input devices.

echo ‘KERNEL==“uinput”, SUBSYSTEM==“misc”, OPTIONS+=“static_node=uinput”, TAG+=“uaccess”’ |
sudo tee /etc/udev/rules.d/85-sunshine.rules

Opening ports in the firewall
you need to open these ports to allow you to connect to sunshine

ufw allow 47984/tcp
ufw allow 47989/tcp
ufw allow 48010/tcp
ufw allow 47998/udp
ufw allow 47999/udp
ufw allow 48000/udp
ufw allow 48002/udp
ufw allow 48010/udp

Autostarting sunshine
First in the home directory of the user you have set to autologin you’ll need to make the required directory for systemd user services

mkdir ./.config/systemd/user/

Next make the systemd service file. This file is set to start pulseaudio if its not running and only start sunshine after pulseaudio has started.

vi ./.config/systemd/user/Sunshine.service

[Unit]
Description=Sunshine is a self-hosted game stream host for Moonlight.
StartLimitIntervalSec=500
StartLimitBurst=5
Requires=pulseaudio.service
After=pulseaudio.service

[Service]
ExecStart=//usr/bin/sunshine
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=graphical-session.target

Reload the systemctl daemon so you can use the new service file you created.

systemctl --user daemon-reload

Set sunshine to start at boot

systemctl --user enable Sunshine.service

Set systemctl to start the graphical target, so the desktop environment is started on boot

systemctl set-default graphical.target

Now reboot your machine, sunshine should be up and running but it still needs to be configured. You can check its status with

systemctl --user status Sunshine

Configuring sunshine
The Sunshine docs cover this pretty well. Sunshines autoconfig should work fine, but you still need to access the webui for it to pair the client. The webui is only accessible from the host running sunshine on port 47990. You can access this port over ssh using port forwarding with

ssh -L 47990:localhost:47990 -C -l user@remotemachine

The go to http://localhost:47990 and follow the set up directions.

Congrats Sunshine should now be installed and fully operational

3 Likes

Gunna give this a shot tonight with my RTX A5000 and see if I can get acceptable performance from my 1st gen Xeon server over the network!

Nice, let me know how it goes! My servers got a 3080 and a pair of first gen e5 2650 xeons and it runs pretty well. All the encode is handled by the gpu which helps a ton. More constrained by upload bandwidth when out and about then anything else.

Thanks for the tutorial. I have tried this, but had issues with audio - not working for some reason. But maybe that was some wrong server (was trying to use genesiscloud) - because I did not get the full ubuntu desktop at all. If someone is still reading this, let me also know how it works for you :slight_smile:

Do you know some linux GPU provider where this is working ?

UPDATE: Not working anymore, not sure what I am doing wrong, but it is just not working. Pulseaudio not starting, and even sunshine is not able to start, when I remove the dependency. I am following this guide step by step but no success.

yeah sunshine needs pulseaudio no matter what. run systemctl status pulse and see what the error log says. Did you do the step to disable bluetooth? that can cause puleaudio to crash if you don’t.

Did Debian and is derivatives not move from PulseAudio to Pipewire? I know this has caused me issues with audio redirection for xRDP, I wonder if that is the same for Sunshine/Moonlight.

Your right it is pipewire. If sunshine can’t set up an pipewire audio sync it crashes when you try and connect.

Dont get this to work:

[2023:06:04:07:34:49]: Info: Sunshine version: v0.20.0
[2023:06:04:07:34:49]: Warning: Failed to create system tray
[2023:06:04:07:34:49]: Error: Failed to create session: Unable to open display
[2023:06:04:07:34:49]: Error: Couldn’t expose some/all drm planes for card: /dev/dri/card0
[2023:06:04:07:34:49]: Error: Unable to initialize capture method
[2023:06:04:07:34:49]: Error: Platform failed to initialize
[2023:06:04:07:34:49]: Error: Could not create Sunshine Mouse: Permission denied
[2023:06:04:07:34:49]: Error: Could not create Sunshine Touchscreen: Permission denied
[2023:06:04:07:34:49]: Error: Could not create Sunshine Keyboard: Permission denied
[2023:06:04:07:34:49]: Error: Unable to create some input devices! Are you a member of the ‘input’ group?
[2023:06:04:07:34:49]: Info: Falling back to XTest
[2023:06:04:07:34:49]: Info: // Testing for available encoders, this may generate errors. You can safely ignore those errors. //
[2023:06:04:07:34:49]: Info: Trying encoder [nvenc]
[2023:06:04:07:34:51]: Info: Encoder [nvenc] failed
[2023:06:04:07:34:51]: Info: Trying encoder [vaapi]
[2023:06:04:07:34:52]: Info: Encoder [vaapi] failed
[2023:06:04:07:34:52]: Info: Trying encoder [software]
[2023:06:04:07:34:54]: Info: Encoder [software] failed
[2023:06:04:07:34:54]: Fatal: Couldn’t find any working encoder
[2023:06:04:07:34:54]: Error: Video failed to find working encoder
[2023:06:04:07:34:54]: Info: Adding avahi service Sunshine
[2023:06:04:07:34:55]: Info: Avahi service Sunshine successfully established.

Any idea?
Followed exactly your description, two times…

Stuck at this aswell. For some reasons it does not correctly create the X11 display. Maybe someone has a hint or working setup.

I managed to get this working just once, not sure what I did :slight_smile: but even that I needed to disable the audio. I will try to do this once more, and will paste the output of pulseaudio error. Basically the pulseaudio service was not able to start (too quick or something like that). Of course I created a new default.pa file in my user’s home dir.

Yes, this thread needs some update and updated instructions, now I am not able to achieve it in any way :frowning:

Sorry this is on me I forgot to put this in the guide and lumped it in with the link to sunshines configuration page. looks like you’ve got two problems. First try this step from the sunshine docs creating a udev rule to allowing sunshine to create input devices.

echo 'KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"' | \
sudo tee /etc/udev/rules.d/85-sunshine.rules

See if the failed to create input errors go away.
As for the finding an encoder error I’m not sure without knowing more about your setup. I’ve only tried this with consumer nvidia cards. But if the drivers been installed, patched, and the systems been rebooted. it should be able to find the nvfb driver.

Thanks! Unfortunately I haven’t yet managed to get this working.
It seems to be related to gdm. If I just start
Xorg :0 -config xorg.conf -noreset
and start sunshine, nvenc works and I get a connection. However, gdm does not work.

Hmm. Heres a copy of my full gdm config file. Hopefully it helps.

GDM configuration storage

See /usr/share/gdm/gdm.schemas for a list of available options.

[daemon]

Uncomment the line below to force the login screen to use Xorg

WaylandEnable=false

Enabling automatic login

AutomaticLoginEnable = true
AutomaticLogin = user

Enabling timed login

TimedLoginEnable = true

TimedLogin = user1

TimedLoginDelay = 10

[security]
DisallowTCP=false
[xdmcp]

[chooser]

[debug]

Uncomment the line below to turn on debugging

More verbose logs

Additionally lets the X server dump core if it crashes

#Enable=true