Headless Sunshine Game Streaming Setup on Ubuntu 24.04 (Xorg)

This guide outlines the definitive setup for running the LizardByte Sunshine game streaming server on a headless Ubuntu 24.04 system.

It specifically solves the common “race condition” boot failures and the “Unable to open display” app launch crashes (commonly seen with Steam) by utilizing a supervised, custom systemd user service mapped explicitly to the Xorg session.

Phase 1: Force Auto-Login (The Headless Fix)

Because there is no physical monitor, Ubuntu will not launch a graphical environment (xdg-desktop-autostart.target) until a user logs in. We must force GDM3 to auto-login the primary user so the Xorg server starts rendering the desktop in the background.

1. Open the display manager config:

sudo nano /etc/gdm3/custom.conf

2. Under the [daemon] section, uncomment and set the following (replace YOUR_USERNAME with your actual Linux user):

[daemon]
AutomaticLoginEnable=true
AutomaticLogin=YOUR_USERNAME

3. Save, exit, and reboot the system:

sudo reboot

Phase 2: Clean Installation

Always install the .deb package. Avoid the Flatpak version, as its heavy sandboxing completely breaks the ability to run local master scripts or trigger host applications natively.

1. Download the latest .deb for Ubuntu 24.04 from the LizardByte GitHub Releases page.

2. Install the package and force dependency resolution:

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

Phase 3: Nuke the Default Services

The default system-level and user-level systemd hooks provided by the package are notoriously fragile on headless setups. We must kill them to prevent port conflicts (Address already in use) and permission denials (like PulseAudio access).

Run these commands to strip out the default hooks:

sudo systemctl stop sunshine
sudo systemctl disable sunshine
systemctl --user stop sunshine
systemctl --user disable sunshine

Phase 4: Create the Bulletproof Custom Service

To ensure Sunshine survives crashes, waits for the user login rather than the buggy graphical targets, and has the proper permissions to launch UI apps like Steam, we build a custom user-level service.

1. Create the user systemd directory:

mkdir -p ~/.config/systemd/user

2. Create the custom service file:

nano ~/.config/systemd/user/sunshine.service

3. Paste the following configuration. (Note: The Environment variables are critical. They inject the exact display coordinates into Sunshine. Without them, apps launched from Moonlight will crash with a segmentation fault/assertion failed error because they cannot find the headless display).

[Unit]
Description=Sunshine Game Stream Server (Supervised)
After=network.target

[Service]
# Explicitly pass the display coordinates to fix "Unable to open display" crashes
# Note: UID 1000 is standard for the primary user. Change if yours differs.
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/run/user/1000/gdm/Xauthority"

ExecStart=/usr/bin/sunshine

# Aggressive restart logic if the stream crashes or boots faster than the GPU initializes
Restart=always
RestartSec=5

[Install]
# Bind to the user login, ignoring the traditional graphical boot targets
WantedBy=default.target

Phase 5: Enable, Start, and Linger

Finally, we lock the new service in place and tell Linux to keep this user’s services running even if the desktop session is backgrounded.

# Reload systemd to recognize the custom file
systemctl --user daemon-reload

# Enable and start the service
systemctl --user enable sunshine
systemctl --user start sunshine

# Force the user's services to survive reboots unattended
loginctl enable-linger $USER

Verification

1. Check the service status to ensure it is active (running):

systemctl --user status sunshine

2. Navigate to https://<server-ip>:47990 from another machine to access the Web UI and begin adding applications.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *