Sunshine Documentation

Self-hosted game stream host for Moonlight.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy Sunshine on any server, homelab, or cloud container platform.

1. Project Overview & Quickstart (LizardByte/Sunshine)

File: README.md

โ„น๏ธ About

Sunshine is a self-hosted game stream host for Moonlight.
Offering low-latency, cloud gaming server capabilities with support for AMD, Intel, and Nvidia GPUs for hardware
encoding. Software encoding is also available. You can connect to Sunshine from any Moonlight client on a variety of
devices. A web UI is provided to allow configuration, and client pairing, from your favorite web browser. Pair from
the local server or any mobile device.

LizardByte has the full documentation hosted on Read the Docs

๐ŸŽฎ Feature Compatibility

Feature FreeBSD Linux macOS Windows
What type of gamepads can be emulated on the host.
text
Clients may support other gamepads. |  |  |  |  |

| Generic | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| DualShock / DS4 (PlayStation 4) | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| DualSense / DS5 (PlayStation 5) | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| Nintendo Switch Pro | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| Xbox 360 | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| Xbox One | ๐ŸŸก1 | โœ… | โŒ | โœ… |
| Xbox Series | ๐ŸŸก1 | โœ… | โŒ | โœ… |

[!NOTE]
1 Missing motion, touchpad input, battery state, RGB LEDs, adaptive triggers, and raw HID output reports.

Encoding API GPU Vendor FreeBSD Linux macOS Windows
AMF AMD โž– โž– โž– โœ…
Media Foundation Qualcomm โž– โž– โž– โœ…
NVENC NVIDIA โž– โœ… โž– โœ…
QuickSync Intel โž– โž– โž– โœ…
VAAPI AMD โœ… โœ… โž– โž–
Intel โœ… โœ… โž– โž–
NVIDIA โž– โœ… โž– โž–
Video Toolbox Apple โž– โž– โœ… โž–
Intel โž– โž– โœ… โž–
Vulkan Video AMD ๐ŸŸก โœ… โž– โž–
Intel ๐ŸŸก ๐ŸŸก โž– โž–
NVIDIA โž– ๐ŸŸก โž– โž–
Software Any โœ… โœ… โœ… โœ…
Capture Method FreeBSD Linux macOS Windows
DXGI Desktop Duplication โž– โž– โž– โœ…
KMS/DRM โœ… โœ… โž– โž–
NvFBC (X11 only) โž– โœ… โž– โž–
ScreenCaptureKit โž– โž– โœ… โž–
Wayland (wlroots) โœ… โœ… โž– โž–
Windows.Graphics.Capture โž– โž– โž– ๐ŸŸก
  โ†ณ Portable โž– โž– โž– โœ…
  โ†ณ Service โž– โž– โž– โŒ
X11 โœ… โœ… โž– โž–
XDG Desktop Portal โœ… โœ… โž– โž–
KWin Screencast โœ… โœ… โž– โž–
Capture Method VAAPI Vulkan Video NVENC (CUDA) Software
KMS/DRM โœ… โœ… โœ… โœ…
NvFBC โŒ โŒ โœ… โŒ
Wayland (wlroots) โœ… โŒ โœ… โœ…
X11 โœ… โŒ โœ… โœ…
XDG Desktop Portal โœ… โœ… โœ… โœ…
KWin Screencast โœ… โœ… โœ… โœ…

Legend: โœ… Supported | ๐ŸŸก Partial Support | โŒ Not Yet Supported | โž– Not Applicable

๐Ÿ–ฅ๏ธ System Requirements

[!WARNING]
These tables are a work in progress. Do not purchase hardware based on this information.

Component Requirement
GPU AMD: VCE 1.0 or higher, see: obs-amd hardware support
Intel:
text
  FreeBSD/Linux: VAAPI-compatible, see: [VAAPI hardware support](https://www.intel.com/content/www/us/en/developer/articles/technical/linuxmedia-vaapi.html)
          Windows: Skylake or newer with QuickSync encoding support |  |

| Nvidia: NVENC enabled cards, see: nvenc support matrix | |
| CPU | AMD: Ryzen 3 or higher |
| Intel: Core i3 or higher | |
| RAM | 4GB or more |
| OS | FreeBSD: 15.1+ |
| Linux/Debian: 13+ (trixie) | |
| Linux/Fedora: 43+ | |
| Linux/Ubuntu: 22.04+ (jammy) | |
| macOS: 14.2+ | |
| Windows: 11+ | |
| Network | Host: 5GHz, 802.11ac |
| Client: 5GHz, 802.11ac | |

Component Requirement
GPU AMD: Video Coding Engine 3.1 or higher
Intel:
text
  FreeBSD/Linux: HD Graphics 510 or higher
          Windows: Skylake or newer with QuickSync encoding support |  |

| Nvidia:
  FreeBSD/Linux: GeForce RTX 2000 series or higher
  Windows: Geforce GTX 1080 or higher | |
| CPU | AMD: Ryzen 5 or higher |
| Intel: Core i5 or higher | |
| Network | Host: CAT5e ethernet or better |
| Client: CAT5e ethernet or better | |

Component Requirement
GPU AMD: Video Coding Engine 3.4 or higher
Intel: HD Graphics 730 or higher
Nvidia: Pascal-based GPU (GTX 10-series) or higher
CPU AMD: Ryzen 5 or higher
Intel: Core i5 or higher
Network Host: CAT5e ethernet or better
Client: CAT5e ethernet or better

โ“ Support

Our support methods are listed in our LizardByte Docs.

๐Ÿ’ฒ Sponsors and Supporters

๐Ÿ‘ฅ Contributors

Thank you to all the contributors who have helped make Sunshine better!

GitHub

CrowdIn

Previous Next
Getting Started

[TOC]


File: docs/api.md

API

Sunshine has a RESTful API which can be used to interact with the service.

Unless otherwise specified, authentication is required for all API calls. You can authenticate using
basic authentication with the admin username and password.

CSRF Protection

State-changing API endpoints (POST, DELETE) are protected against Cross-Site Request Forgery (CSRF) attacks.

For Web Browsers:

  • Requests from same-origin (configured via csrf_allowed_origins) are automatically allowed
  • Cross-origin requests require a CSRF token

For Non-Browser Applications:

  • Non-browser clients (e.g. curl, scripts, custom apps) are exempt from CSRF protection
  • CSRF attacks require a browser to silently attach credentials to a cross-origin request โ€” this threat
    does not apply to non-browser clients that explicitly provide credentials with every request
  • Requests with no Origin or Referer header (as is typical for non-browser clients) are automatically
    allowed without a CSRF token

Example (browser-equivalent cross-origin request):

bash
# Get CSRF token
curl -u user:pass https://localhost:47990/api/csrf-token

# Use token in request
curl -u user:pass -H "X-CSRF-Token: your_token_here" \
  -X POST https://localhost:47990/api/restart

@htmlonly

@endhtmlonly

GET /api/csrf-token

@copydoc confighttp::getCSRFToken()

GET /api/apps

@copydoc confighttp::getApps()

POST /api/apps

@copydoc confighttp::saveApp()

POST /api/apps/close

@copydoc confighttp::closeApp()

DELETE /api/apps/{index}

@copydoc confighttp::deleteApp()

GET /api/browse

@copydoc confighttp::browseDirectory()

GET /api/clients/list

@copydoc confighttp::getClients()

POST /api/clients/unpair

@copydoc confighttp::unpair()

POST /api/clients/unpair-all

@copydoc confighttp::unpairAll()

POST /api/clients/update

@copydoc confighttp::updateClient()

GET /api/config

@copydoc confighttp::getConfig()

GET /api/configLocale

@copydoc confighttp::getLocale()

POST /api/config

@copydoc confighttp::saveConfig()

GET /api/covers/{index}

@copydoc confighttp::getCover()

POST /api/covers/upload

@copydoc confighttp::uploadCover()

GET /api/logs

@copydoc confighttp::getLogs()

POST /api/password

@copydoc confighttp::savePassword()

POST /api/pin

@copydoc confighttp::savePin()

POST /api/reset-display-device-persistence

@copydoc confighttp::resetDisplayDevicePersistence()

POST /api/restart

@copydoc confighttp::restart()

GET /api/virtual-input/status

@copydoc confighttp::getVirtualInputStatus()

Previous Next
Performance Tuning Troubleshooting

[TOC]


File: docs/app_examples.md

App Examples

Since not all applications behave the same, we decided to create some examples to help you get started adding games
and applications to Sunshine.

[!TIP]
Throughout these examples, any fields not shown are left blank. You can enhance your experience by
adding an image or a log file (via the Output field).

[!WARNING]
When a working directory is not specified, it defaults to the folder where the target application resides.

Common Examples

Desktop

Field Value
Application Name @code{}Desktop@endcode
Image @code{}desktop.png@endcode

Steam Big Picture

[!NOTE]
Steam is launched as a detached command because Steam starts with a process that self updates itself and the original
process is killed.

@tabs{
@tab{FreeBSD |
| Field | Value |
|------------------------------|------------------------------------------------------|
| Application Name | @code{}Steam Big Picture@endcode |
| Command Preporations -> Undo | @code{}setsid steam steam://close/bigpicture@endcode |
| Detached Commands | @code{}setsid steam steam://open/bigpicture@endcode |
| Image | @code{}steam.png@endcode |
}
@tab{Linux |
| Field | Value |
|------------------------------|------------------------------------------------------|
| Application Name | @code{}Steam Big Picture@endcode |
| Command Preporations -> Undo | @code{}setsid steam steam://close/bigpicture@endcode |
| Detached Commands | @code{}setsid steam steam://open/bigpicture@endcode |
| Image | @code{}steam.png@endcode |
}
@tab{macOS |
| Field | Value |
|------------------------------|------------------------------------------------|
| Application Name | @code{}Steam Big Picture@endcode |
| Command Preporations -> Undo | @code{}open steam://close/bigpicture@endcode |
| Detached Commands | @code{}open steam://open/bigpicture@endcode |
| Image | @code{}steam.png@endcode |
}
@tab{Windows |
| Field | Value |
|------------------------------|-------------------------------------------|
| Application Name | @code{}Steam Big Picture@endcode |
| Command Preporations -> Undo | @code{}steam://close/bigpicture@endcode |
| Detached Commands | @code{}steam://open/bigpicture@endcode |
| Image | @code{}steam.png@endcode |
}
}

Epic Game Store game

[!NOTE]
Using the URI method will be the most consistent between various games.

URI

@tabs{
@tab{Windows |
| Field | Value |
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Commands | @code{}com.epicgames.launcher://apps/d759128018124dcabb1fbee9bb28e178%3A20729b9176c241f0b617c5723e70ec2d%3AOvenbird?action=launch&silent=true@endcode |
}
}

Binary (w/ working directory

@tabs{
@tab{Windows |
| Field | Value |
|-------------------|------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}MarsEpic.exe@endcode |
| Working Directory | @code{}"C:\Program Files\Epic Games\SurvivingMars"@endcode |
}
}

Binary (w/o working directory)

@tabs{
@tab{Windows |
| Field | Value |
|-------------------|-------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}"C:\Program Files\Epic Games\SurvivingMars\MarsEpic.exe"@endcode |
}
}

Steam game

[!NOTE]
Using the URI method will be the most consistent between various games.

URI

@tabs{
@tab{FreeBSD |
| Field | Value |
|-------------------|------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Detached Commands | @code{}setsid steam steam://rungameid/464920@endcode |
}
@tab{Linux |
| Field | Value |
|-------------------|------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Detached Commands | @code{}setsid steam steam://rungameid/464920@endcode |
}
@tab{macOS |
| Field | Value |
|-------------------|----------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Detached Commands | @code{}open steam://rungameid/464920@endcode |
}
@tab{Windows |
| Field | Value |
|-------------------|-----------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Detached Commands | @code{}steam://rungameid/464920@endcode |
}
}

Binary (w/ working directory

@tabs{
@tab{FreeBSD |
| Field | Value |
|-------------------|--------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}MarsSteam@endcode |
| Working Directory | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode |
}
@tab{Linux |
| Field | Value |
|-------------------|--------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}MarsSteam@endcode |
| Working Directory | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode |
}
@tab{macOS |
| Field | Value |
|-------------------|--------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}MarsSteam@endcode |
| Working Directory | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode |
}
@tab{Windows |
| Field | Value |
|-------------------|-------------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}MarsSteam.exe@endcode |
| Working Directory | @code{}"C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars"@endcode |
}
}

Binary (w/o working directory)

@tabs{
@tab{FreeBSD |
| Field | Value |
|-------------------|------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode |
}
@tab{Linux |
| Field | Value |
|-------------------|------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode |
}
@tab{macOS |
| Field | Value |
|-------------------|------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode |
}
@tab{Windows |
| Field | Value |
|-------------------|---------------------------------------------------------------------------------------------|
| Application Name | @code{}Surviving Mars@endcode |
| Command | @code{}"C:\Program Files (x86)\Steam\steamapps\common\Surviving Mars\MarsSteam.exe"@endcode |
}
}

Prep Commands

Changing Resolution and Refresh Rate

Linux

X11

Prep Step Command
Do @code{}sh -c "xrandr --output HDMI-1 --mode ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --rate ${SUNSHINE_CLIENT_FPS}"@endcode
Undo @code{}xrandr --output HDMI-1 --mode 3840x2160 --rate 120@endcode

[!TIP]
The above only works if the xrandr mode already exists. You will need to create new modes to stream to macOS
and iOS devices, since they use non-standard resolutions.

You can update the Do command to this:

bash
bash -c "${HOME}/scripts/set-custom-res.sh \"${SUNSHINE_CLIENT_WIDTH}\" \"${SUNSHINE_CLIENT_HEIGHT}\" \"${SUNSHINE_CLIENT_FPS}\""

The set-custom-res.sh will have this content:

bash
#!/bin/bash
set -e

# Get params and set any defaults
width=${1:-1920}
height=${2:-1080}
refresh_rate=${3:-60}

# You may need to adjust the scaling differently so the UI/text isn't too small / big
scale=${4:-0.55}

# Get the name of the active display
display_output=$(xrandr | grep " connected" | awk '{ print $1 }')

# Get the modeline info from the 2nd row in the cvt output
modeline=$(cvt ${width} ${height} ${refresh_rate} | awk 'FNR == 2')
xrandr_mode_str=${modeline//Modeline \"*\" /}
mode_alias="${width}x${height}"

echo "xrandr setting new mode ${mode_alias} ${xrandr_mode_str}"
xrandr --newmode ${mode_alias} ${xrandr_mode_str}
xrandr --addmode ${display_output} ${mode_alias}

# Reset scaling
xrandr --output ${display_output} --scale 1

# Apply new xrandr mode
xrandr --output ${display_output} --primary --mode ${mode_alias} --pos 0x0 --rotate normal --scale ${scale}

# Optional reset your wallpaper to fit to new resolution
# xwallpaper --zoom /path/to/wallpaper.png

Wayland (wlroots, e.g. hyprland)

Prep Step Command
Do @code{}sh -c "wlr-xrandr --output HDMI-1 --mode "${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}Hz""@endcode
Undo @code{}wlr-xrandr --output HDMI-1 --mode 3840x2160@120Hz@endcode

[!TIP]
wlr-xrandr only works with wlroots-based compositors.

Gnome (X11)

Prep Step Command
Do @code{}sh -c "xrandr --output HDMI-1 --mode ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --rate ${SUNSHINE_CLIENT_FPS}"@endcode
Undo @code{}xrandr --output HDMI-1 --mode 3840x2160 --rate 120@endcode

Gnome (Wayland)

Prep Step Command
Do @code{}sh -c "displayconfig-mutter set --connector HDMI-1 --resolution ${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} --refresh-rate ${SUNSHINE_CLIENT_FPS} --hdr ${SUNSHINE_CLIENT_HDR}"@endcode
Undo @code{}displayconfig-mutter set --connector HDMI-1 --resolution 3840x2160 --refresh-rate 120 --hdr false@endcode

Installation instructions for displayconfig-mutter can be found here. Alternatives include
gnome-randr-rust and gnome-randr.py, but both of those are
unmaintained and do not support newer Mutter features such as HDR and VRR.

[!TIP]
HDR support has been added to Gnome 48, to check if your display supports it, you can run this:

text
displayconfig-mutter list

If it doesn't, then remove --hdr flag from both Do and Undo steps.

KDE Plasma (Wayland, X11)

Prep Step Command
Do @code{}sh -c "kscreen-doctor output.HDMI-A-1.mode.${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}"@endcode
Undo @code{}kscreen-doctor output.HDMI-A-1.mode.3840x2160@120@endcode

[!CAUTION]
The names of your displays will differ between X11 and Wayland.
Be sure to use the correct name, depending on your session manager.
e.g., On X11, the monitor may be called HDMI-A-0, but on Wayland, it may be called HDMI-A-1.

[!TIP]
Replace HDMI-A-1 with the display name of the monitor you would like to use for Moonlight.
You can list the monitors available to you with:

text
kscreen-doctor -o

These will also give you the supported display properties for each monitor. You can select them either by
hard-coding their corresponding number (e.g. kscreen-doctor output.HDMI-A1.mode.0) or using the above
do command to fetch the resolution requested by your Moonlight client
(which has a chance of not being supported by your monitor).

NVIDIA

Prep Step Command
Do @code{}sh -c "nvidia-settings -a CurrentMetaMode="HDMI-1: nvidia-auto-select { ViewPortIn=${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}, ViewPortOut=${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}+0+0 }""@endcode
Undo @code{}nvidia-settings -a CurrentMetaMode="HDMI-1: nvidia-auto-select { ViewPortIn=3840x2160, ViewPortOut=3840x2160+0+0 }"@endcode

macOS

displayplacer

[!NOTE]
This example uses the displayplacer tool to change the resolution.
This tool can be installed following instructions in their
GitHub repository.

Prep Step Command
Do @code{}sh -c "displayplacer "id: res:${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} hz:${SUNSHINE_CLIENT_FPS} scaling:on origin:(0,0) degree:0""@endcode
Undo @code{}displayplacer "id: res:3840x2160 hz:120 scaling:on origin:(0,0) degree:0"@endcode

Windows

Sunshine has built-in support for changing the resolution and refresh rate on Windows. If you prefer to use a
third-party tool, you can use QRes as an example.

QRes

[!NOTE]
This example uses the QRes tool to change the resolution and refresh rate.
This tool can be downloaded from their SourceForge repository.

Prep Step Command
Do @code{}cmd /C "FullPath\qres.exe /x:%SUNSHINE_CLIENT_WIDTH% /y:%SUNSHINE_CLIENT_HEIGHT% /r:%SUNSHINE_CLIENT_FPS%"@endcode
Undo @code{}FullPath\qres.exe /x:3840 /y:2160 /r:120@endcode

Additional Considerations

Linux (Flatpak)

[!CAUTION]
Because Flatpak packages run in a sandboxed environment and do not normally have access to the
host, the Flatpak of Sunshine requires commands to be prefixed with flatpak-spawn --host.

Windows

Elevating Commands (Windows)

If you've installed Sunshine as a service (default), you can specify if a command should be elevated with
administrative privileges. Simply enable the elevated option in the WEB UI, or add it to the JSON configuration.
This is an option for both prep-cmd and regular commands and will launch the process with the current user without a
UAC prompt.

Example

json
{
  "name": "Game With AntiCheat that Requires Admin",
  "output": "",
  "cmd": "ping 127.0.0.1",
  "exclude-global-prep-cmd": false,
  "elevated": true,
  "prep-cmd": [
    {
      "do": "powershell.exe -command \"Start-Streaming\"",
      "undo": "powershell.exe -command \"Stop-Streaming\"",
      "elevated": false
    }
  ],
  "image-path": ""
}
Previous Next
Configuration Awesome-Sunshine

[TOC]


File: docs/awesome_sunshine.md

Awesome-Sunshine

@htmlonly



@endhtmlonly

Previous Next
App Examples Guides

[TOC]


File: docs/building.md

Building

Sunshine binaries are built using CMake and requires cmake > 3.25.

Building Locally

Compiler

It is recommended to use one of the following compilers:

Compiler Version
GCC 14+
Clang 17+
Apple Clang 15+

Dependencies

FreeBSD

[!CAUTION]
Sunshine support for FreeBSD is experimental and may be incomplete or not work as expected

Install dependencies

sh
pkg install -y \
  audio/opus \
  audio/pulseaudio \
  devel/cmake \
  devel/evdev-proto \
  devel/git \
  devel/libevdev \
  devel/llvm19 \
  devel/ninja \
  devel/pkgconf \
  devel/qt6-base \
  ftp/curl \
  graphics/libdrm \
  graphics/qt6-svg \
  graphics/wayland \
  multimedia/libva \
  net/miniupnpc \
  ports-mgmt/pkg \
  security/openssl \
  shells/bash \
  www/npm-node22 \
  x11/libX11 \
  x11/libxcb \
  x11/libXfixes \
  x11/libXrandr \
  x11/libXtst

Use LLVM 19 when configuring a local FreeBSD build:

sh
export CC=clang19
export CXX=clang++19

Linux

Dependencies vary depending on the distribution. You can reference our
linux_build.sh script for a list of
dependencies we use in Debian-based, Fedora-based and Arch-based distributions. Please submit a PR if you would like to extend the
script to support other distributions.

KMS Capture

If you are using KMS, patching the Sunshine binary with setcap is required. Some post-install scripts handle this. If building
from source and using the binary directly, this will also work:

bash
sudo cp build/sunshine /tmp
sudo setcap cap_sys_admin,cap_sys_nice+p /tmp/sunshine
sudo getcap /tmp/sunshine
sudo mv /tmp/sunshine build/sunshine

CUDA Toolkit

Sunshine requires CUDA Toolkit for NVFBC capture. There are two caveats to CUDA:

  1. The version installed depends on the version of GCC.
  2. The version of CUDA you use will determine compatibility with various GPU generations.
    At the time of writing, the recommended version to use is CUDA ~13.1.
    See CUDA compatibility for more info.

[!NOTE]
To install older versions, select the appropriate run file based on your desired CUDA version and architecture
according to CUDA Toolkit Archive

macOS

You can either use Homebrew or MacPorts to install dependencies.

Homebrew

bash
dependencies=(
  "boost"  # Optional
  "cmake"
  "doxygen"  # Optional, for docs
  "graphviz"  # Optional, for docs
  "icu4c"  # Optional, if boost is not installed
  "miniupnpc"
  "ninja"
  "node"
  "openssl@3"
  "opus"
  "pkg-config"
  "qtbase"
  "qtsvg"
)
brew install "${dependencies[@]}"

If there are issues with an SSL header that is not found:

@tabs{
@tab{ Intel | bash ln -s /usr/local/opt/openssl/include/openssl /usr/local/include/openssl }
@tab{ Apple Silicon | bash ln -s /opt/homebrew/opt/openssl/include/openssl /opt/homebrew/include/openssl
}
}

MacPorts

bash
dependencies=(
  "cmake"
  "curl"
  "doxygen"  # Optional, for docs
  "graphviz"  # Optional, for docs
  "libopus"
  "miniupnpc"
  "ninja"
  "npm9"
  "pkgconfig"
  "qt6-qtbase"
  "qt6-qtsvg"
)
sudo port install "${dependencies[@]}"

Windows

[!WARNING]
Cross-compilation is not supported on Windows. You must build on the target architecture.

First, you need to install MSYS2.

For AMD64 startup "MSYS2 UCRT64" (or for ARM64 startup "MSYS2 CLANGARM64") then execute the following commands.

Update all packages

bash
pacman -Syu

Set toolchain variable

For UCRT64:

bash
export TOOLCHAIN="ucrt-x86_64"

For CLANGARM64:

bash
export TOOLCHAIN="clang-aarch64"

Install dependencies

bash
dependencies=(
  "git"
  "mingw-w64-${TOOLCHAIN}-boost"  # Optional
  "mingw-w64-${TOOLCHAIN}-cmake"
  "mingw-w64-${TOOLCHAIN}-cppwinrt"
  "mingw-w64-${TOOLCHAIN}-curl-winssl"
  "mingw-w64-${TOOLCHAIN}-doxygen"  # Optional, for docs... better to install official Doxygen
  "mingw-w64-${TOOLCHAIN}-graphviz"  # Optional, for docs
  "mingw-w64-${TOOLCHAIN}-miniupnpc"
  "mingw-w64-${TOOLCHAIN}-onevpl"
  "mingw-w64-${TOOLCHAIN}-openssl"
  "mingw-w64-${TOOLCHAIN}-opus"
  "mingw-w64-${TOOLCHAIN}-toolchain"
  "mingw-w64-${TOOLCHAIN}-qt6-static"
)
if [[ "${MSYSTEM}" == "UCRT64" ]]; then
  dependencies+=(
    "mingw-w64-${TOOLCHAIN}-MinHook"
    "mingw-w64-${TOOLCHAIN}-nodejs"
    "mingw-w64-${TOOLCHAIN}-nsis"
  )
fi
pacman -S "${dependencies[@]}"

Static Qt is enabled by default on Windows. Sunshine automatically adds the MSYS2 static Qt prefix at
${MINGW_PREFIX}/qt6-static when that package is installed. If an IDE does not inherit MINGW_PREFIX, Sunshine
derives the same prefix from the selected compiler. If static Qt is installed in a custom location, specify it with
-DCMAKE_PREFIX_PATH=/path/to/qt6-static.

To use dynamic Qt instead, configure with -DSUNSHINE_USE_STATIC_QT=OFF and ensure the dynamic Qt package is
available through the normal toolchain prefix.

To create a WiX installer, you also need to install .NET.

For ARM64: To build frontend, you also need to install Node.JS

Clone

Ensure git is installed on your system, then clone the repository using the following command:

bash
git clone https://github.com/lizardbyte/sunshine.git --recurse-submodules
cd sunshine
mkdir build

Build

bash
cmake -B build -G Ninja -S .
ninja -C build

[!TIP]
Available build options can be found in
options.cmake.

Package

@tabs{
@tab{FreeBSD | @tabs{
@tab{pkg | bash cpack -G FREEBSD --config ./build/CPackConfig.cmake }
}}
@tab{Linux | @tabs{
@tab{deb | bash cpack -G DEB --config ./build/CPackConfig.cmake }
@tab{rpm | bash cpack -G RPM --config ./build/CPackConfig.cmake }
}}
@tab{macOS | @tabs{
@tab{DragNDrop | bash cpack -G DragNDrop --config ./build/CPackConfig.cmake }
}}
@tab{Windows | @tabs{
@tab{NSIS Installer | bash cpack -G NSIS --config ./build/CPackConfig.cmake }
@tab{WiX Installer | bash cpack -G WIX --config ./build/CPackConfig.cmake }
@tab{Portable | bash cpack -G ZIP --config ./build/CPackConfig.cmake }
}}
}

Remote Build

It may be beneficial to build remotely in some cases. This will enable easier building on different operating systems.

  1. Fork the project
  2. Activate workflows
  3. Trigger the CI workflow manually
  4. Download the artifacts/binaries from the workflow run summary
Previous Next
Troubleshooting Contributing

[TOC]


File: docs/configuration.md

Configuration

@admonition{ Host authority | @htmlonly
By providing the host authority (URI + port), you can easily open each configuration option in the config UI.

**Host authority: **
@endhtmlonly
}

Sunshine will work with the default settings for most users. In some cases you may want to configure Sunshine further.

The default location for the configuration file is listed below. You can use another location if you
choose, by passing in the full configuration file path as the first argument when you start Sunshine.

Example

bash
sunshine ~/sunshine_config.conf

The default location of the apps.json is the same as the configuration file. You can use a custom
location by modifying the configuration file.

Default Config Directory

OS Location
Docker @code{}/config@endcode
FreeBSD @code{}~/.config/sunshine@endcode
Linux @code{}~/.config/sunshine@endcode
macOS @code{}~/.config/sunshine@endcode
Windows @code{}%ProgramFiles%\Sunshine\config@endcode

Although it is recommended to use the configuration UI, it is possible manually configure Sunshine by
editing the conf file in a text editor. Use the examples as reference.

General

locale

Description The locale used for Sunshine's user interface.
Default @code{}
text
en
        @endcode |  |

| Example | @code{}
locale = en
@endcode | |
| Choices | bg | Bulgarian |
| cs | Czech | |
| de | German | |
| en | English | |
| en_GB | English (UK) | |
| en_US | English (United States) | |
| es | Spanish | |
| fr | French | |
| it | Italian | |
| ja | Japanese | |
| ko | Korean | |
| pl | Polish | |
| pt | Portuguese | |
| pt_BR | Portuguese (Brazilian) | |
| ru | Russian | |
| sv | Swedish | |
| tr | Turkish | |
| uk | Ukranian | |
| zh | Chinese (Simplified) | |
| zh_TW | Chinese (Traditional) | |

sunshine_name

Description The name displayed by Moonlight.
Default PC hostname
Example @code{}
text
sunshine_name = Sunshine
        @endcode |

min_log_level

Description The minimum log level printed to standard out.
Default @code{}
text
info
        @endcode |  |

| Example | @code{}
min_log_level = info
@endcode | |
| Choices | verbose | All logging message.
@attention{This may negatively affect streaming performance.} |
| debug | Debug log messages and higher.
@attention{This may negatively affect streaming performance.} | |
| info | Informational log messages and higher. | |
| warning | Warning log messages and higher. | |
| error | Error log messages and higher. | |
| fatal | Only fatal log messages. | |
| none | No log messages. | |

global_prep_cmd

| Description | A list of commands to be run before/after all applications.
If any of the prep-commands fail, starting the application is aborted. |

| --- | --- |
| Default | @code{}
[]
@endcode |
| Example | @code{}
global_prep_cmd = [{"do":"nircmd.exe setdisplay 1280 720 32 144","elevated":true,"undo":"nircmd.exe setdisplay 2560 1440 32 144"}]
@endcode |

notify_pre_releases

Description Whether to be notified of new pre-release versions of Sunshine.
Default @code{}
text
disabled
        @endcode |

| Example | @code{}
notify_pre_releases = disabled
@endcode |

system_tray

Description Show icon in system tray and display desktop notifications
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
system_tray = enabled
@endcode |

Input

controller

Description Whether to allow controller input from the client.
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
controller = enabled
@endcode |

gamepad

| Description | The type of gamepad to emulate on the host.
@note{This option applies to FreeBSD, Linux, and Windows.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
gamepad = auto
@endcode | |
| Choices | generic | Generic HID gamepad |
| ds4 | DualShock 4 controller (PS4) | |
| ds5 | DualShock 5 controller (PS5) | |
| switch | Switch Pro controller | |
| x360 | Xbox 360 controller | |
| xone | Xbox One controller | |
| xseries | Xbox Series controller | |

ds4_back_as_touchpad_click

| Description | Allow Select/Back inputs to also trigger a PlayStation-style gamepad touchpad click. Useful
for clients looking to emulate touchpad click on XInput devices.
@hint{Applies to ds4, ds5, and automatically selected PlayStation-style gamepads.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
ds4_back_as_touchpad_click = enabled
@endcode |

motion_as_ds4

| Description | If a client reports that a connected gamepad has motion sensor support, emulate it on the
host as a PlayStation-style controller.

text
When disabled, motion sensors will not be taken into account during gamepad type selection.
        @hint{Only applies when gamepad is set to auto.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
motion_as_ds4 = enabled
@endcode |

touchpad_as_ds4

| Description | If a client reports that a connected gamepad has a touchpad, emulate it on the host as a
PlayStation-style controller.

text
When disabled, touchpad presence will not be taken into account during gamepad type selection.
        @hint{Only applies when gamepad is set to auto.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
touchpad_as_ds4 = enabled
@endcode |

virtualhid_randomize_mac

Description Randomize the MAC address for PlayStation-style virtual controllers created by libvirtualhid.
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
virtualhid_randomize_mac = enabled
@endcode |

back_button_timeout

| Description | If the Back/Select button is held down for the specified number of milliseconds,
a Home/Guide button press is emulated.
@tip{If back_button_timeout < 0, then the Home/Guide button will not be emulated.} |

| --- | --- |
| Default | @code{}
-1
@endcode |
| Example | @code{}
back_button_timeout = 2000
@endcode |

keyboard

Description Whether to allow keyboard input from the client.
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
keyboard = enabled
@endcode |

key_repeat_delay

| Description | The initial delay, in milliseconds, before repeating keys. Controls how fast keys will
repeat themselves. |

| --- | --- |
| Default | @code{}
500
@endcode |
| Example | @code{}
key_repeat_delay = 500
@endcode |

key_repeat_frequency

| Description | How often keys repeat every second.
@tip{This configurable option supports decimals.} |

| --- | --- |
| Default | @code{}
24.9
@endcode |
| Example | @code{}
key_repeat_frequency = 24.9
@endcode |

always_send_scancodes

| Description | Sending scancodes enhances compatibility with games and apps but may result in incorrect keyboard input
from certain clients that aren't using a US English keyboard layout.

text
Enable if keyboard input is not working at all in certain applications.
        
        
        Disable if keys on the client are generating the wrong input on the host.
        @caution{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
always_send_scancodes = enabled
@endcode |

key_rightalt_to_key_win

| Description | It may be possible that you cannot send the Windows Key from Moonlight directly. In those cases it may be useful to
make Sunshine think the Right Alt key is the Windows key. |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
key_rightalt_to_key_win = enabled
@endcode |

mouse

Description Whether to allow mouse input from the client.
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
mouse = enabled
@endcode |

high_resolution_scrolling

| Description | When enabled, Sunshine will pass through high resolution scroll events from Moonlight clients.

text
This can be useful to disable for older applications that scroll too fast with high resolution scroll
        events. |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
high_resolution_scrolling = enabled
@endcode |

native_pen_touch

| Description | When enabled, Sunshine will pass through native pen/touch events from Moonlight clients.

text
This can be useful to disable for older applications without native pen/touch support. |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
native_pen_touch = enabled
@endcode |

keybindings

| Description | Sometimes it may be useful to map keybindings. Wayland won't allow clients to capture the Win Key
for example.
@tip{See virtual key codes}
@hint{keybindings needs to have a multiple of two elements.}
@note{This option is not available in the UI. A PR would be welcome.} |

| --- | --- |
| Default | @code{}
[
0x10, 0xA0,
0x11, 0xA2,
0x12, 0xA4
]
@endcode |
| Example | @code{}
keybindings = [
0x10, 0xA0,
0x11, 0xA2,
0x12, 0xA4,
0x4A, 0x4B
]
@endcode |

Audio/Video

audio_sink

| Description | The name of the audio sink used for audio loopback.
@tip{To find the name of the audio sink follow these instructions.

text
**FreeBSD/Linux + pulseaudio:**
        
        @code{}
        pacmd list-sinks   grep "name:"
        @endcode
        
        
        **FreeBSD/Linux + pipewire:**
        
        @code{}
        pactl info   grep Source
        # in some causes you'd need to use the `Sink` device, if `Source` doesn't work, so try:
        pactl info   grep Sink
        @endcode
        
        
        **macOS:**
        
        Sunshine can only access microphones on macOS due to system limitations.
        To stream system audio use
        [Soundflower](https://github.com/mattingalls/Soundflower) or
        [BlackHole](https://github.com/ExistentialAudio/BlackHole).
        
        
        **Windows:**
        
        Enter the following command in command prompt or PowerShell.
        @code{}
        %ProgramFiles%\Sunshine\tools\audio-info.exe
        @endcode
        If you have multiple audio devices with identical names, use the Device ID instead.
        }
        @attention{If you want to mute the host speakers, use
        [virtual_sink](#virtual_sink) instead.} |

| --- | --- |
| Default | Sunshine will select the default audio device. |
| Example (FreeBSD/Linux) | @code{}
audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo
@endcode |
| Example (macOS) | @code{}
audio_sink = BlackHole 2ch
@endcode |
| Example (Windows) | @code{}
audio_sink = Speakers (High Definition Audio Device)
@endcode |

virtual_sink

| Description | The audio device that's virtual, like Steam Streaming Speakers. This allows Sunshine to stream audio,
while muting the speakers.
@tip{See audio_sink!}
@tip{These are some options for virtual sound devices.
* Stream Streaming Speakers (Linux, macOS, Windows)
* Steam must be installed.
* Enable install_steam_audio_drivers
or use Steam Remote Play at least once to install the drivers.
* Virtual Audio Cable (macOS, Windows)
} |

| --- | --- |
| Default | n/a |
| Example | @code{}
virtual_sink = Steam Streaming Speakers
@endcode |

stream_audio

Description Whether to stream audio or not. Disabling this can be useful for streaming headless displays as second monitors.
Default @code{}
text
enabled
        @endcode |

| Example | @code{}
stream_audio = disabled
@endcode |

install_steam_audio_drivers

| Description | Installs the Steam Streaming Speakers driver (if Steam is installed) to support surround sound and muting
host audio.
@note{This option is only supported on Windows.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
install_steam_audio_drivers = enabled
@endcode |

adapter_name

| Description | Select the video card you want to stream.
@tip{To find the appropriate values follow these instructions.

text
**FreeBSD/Linux + VA-API:**
        
        Unlike with *amdvce* and *nvenc*, it doesn't matter if video encoding is done on a different GPU.
        @code{}
        ls /dev/dri/renderD*  # to find all devices capable of VAAPI
        # replace ``renderD129`` with the device from above to list the name and capabilities of the device
        vainfo --display drm --device /dev/dri/renderD129   \
          grep -E "((VAProfileH264High VAProfileHEVCMain VAProfileHEVCMain10).*VAEntrypointEncSlice) Driver version"
        @endcode
        To be supported by Sunshine, it needs to have at the very minimum:
        `VAProfileH264High   : VAEntrypointEncSlice`
        
        
        **Windows:**
        
        Enter the following command in command prompt or PowerShell.
        @code{}
        %ProgramFiles%\Sunshine\tools\dxgi-info.exe
        @endcode
        For hybrid graphics systems, DXGI reports the outputs are connected to whichever graphics
        adapter that the application is configured to use, so it's not a reliable indicator of how the
        display is physically connected.
        } |

| --- | --- |
| Default | Sunshine will select the default video card. |
| Example (FreeBSD/Linux) | @code{}
adapter_name = /dev/dri/renderD128
@endcode |
| Example (Windows) | @code{}
adapter_name = Radeon RX 580 Series
@endcode |

output_name

| Description | Select the display number you want to stream.
@tip{To find the appropriate values follow these instructions.

text
**FreeBSD/Linux:**
        
        During Sunshine startup, you should see the list of detected displays:
        @code{}
        Info: Detecting displays
        Info: Detected display: DVI-D-0 (id: 0) connected: false
        Info: Detected display: HDMI-0 (id: 1) connected: true
        Info: Detected display: DP-0 (id: 2) connected: true
        Info: Detected display: DP-1 (id: 3) connected: false
        Info: Detected display: DVI-D-1 (id: 4) connected: false
        @endcode
        It is recommended to use the stable display connector name (text right before the parenthesis, e.g. DP-0) for this value.
        For wlgrab/x11grab and kmsgrab the numeric id value can also be used.
        
        
        **macOS:**
        
        During Sunshine startup, you should see the list of detected displays:
        @code{}
        Info: Detecting displays
        Info: Detected display: Monitor-0 (id: 3) connected: true
        Info: Detected display: Monitor-1 (id: 2) connected: true
        @endcode
        You need to use the id value inside the parenthesis, e.g. `3`.
        
        
        **Windows:**
        
        During Sunshine startup, you should see the list of detected displays:
        @code{}
        Info: Currently available display devices:
        [
          {
            "device_id": "{64243705-4020-5895-b923-adc862c3457e}",
            "display_name": "",
            "friendly_name": "IDD HDR",
            "info": null
          },
          {
            "device_id": "{77f67f3e-754f-5d31-af64-ee037e18100a}",
            "display_name": "",
            "friendly_name": "SunshineHDR",
            "info": null
          },
          {
            "device_id": "{daeac860-f4db-5208-b1f5-cf59444fb768}",
            "display_name": "\\\\.\\DISPLAY1",
            "friendly_name": "ROG PG279Q",
            "info": {
              "hdr_state": null,
              "origin_point": {
                "x": 0,
                "y": 0
              },
              "primary": true,
              "refresh_rate": {
                "type": "rational",
                "value": {
                  "denominator": 1000,
                  "numerator": 119998
                }
              },
              "resolution": {
                "height": 1440,
                "width": 2560
              },
              "resolution_scale": {
                "type": "rational",
                "value": {
                  "denominator": 100,
                  "numerator": 100
                }
              }
            }
          }
        ]
        @endcode
        You need to use the `device_id` value.
        } |

| --- | --- |
| Default | Sunshine will select the default display. |
| Example (FreeBSD/Linux) | @code{}
output_name = 0
@endcode |
| Example (macOS) | @code{}
output_name = 3
@endcode |
| Example (Windows) | @code{}
output_name = {daeac860-f4db-5208-b1f5-cf59444fb768}
@endcode |

dd_configuration_option

| Description | Perform mandatory verification and additional configuration for the display device.
@note{Applies to Windows only.} | |

| --- | --- | --- |
| Default | @code{}
disabled
@endcode | |
| Example | @code{}
dd_configuration_option = ensure_only_display
@endcode | |
| Choices | disabled | Perform no additional configuration (disables all dd_ configuration options). |
| verify_only | Verify that display is active only (this is a mandatory step without any extra steps to verify display state). | |
| ensure_active | Activate the display if it's currently inactive. | |
| ensure_primary | Activate the display if it's currently inactive and make it primary. | |
| ensure_only_display | Activate the display if it's currently inactive and disable all others. | |

dd_resolution_option

| Description | Perform additional resolution configuration for the display device.
@note{"Optimize game settings" must be enabled in Moonlight for this option to work.}
@note{Applies to Windows only.} | |

| --- | --- | --- |
| Default | @code{}auto@endcode | |
| Example | @code{}
dd_resolution_option = manual
@endcode | |
| Choices | disabled | Perform no additional configuration. |
| auto | Change resolution to the requested resolution from the client. | |
| manual | Change resolution to the user specified one (set via dd_manual_resolution). | |

dd_manual_resolution

| Description | Specify manual resolution to be used.
@note{dd_resolution_option must be set to manual}
@note{Applies to Windows only.} |

| --- | --- |
| Default | n/a |
| Example | @code{}
dd_manual_resolution = 1920x1080
@endcode |

dd_refresh_rate_option

| Description | Perform additional refresh rate configuration for the display device.
@note{Applies to Windows only.} | |

| --- | --- | --- |
| Default | @code{}auto@endcode | |
| Example | @code{}
dd_refresh_rate_option = manual
@endcode | |
| Choices | disabled | Perform no additional configuration. |
| auto | Change refresh rate to the requested FPS value from the client. | |
| manual | Change refresh rate to the user specified one (set via dd_manual_refresh_rate). | |

dd_manual_refresh_rate

| Description | Specify manual refresh rate to be used.
@note{dd_refresh_rate_option must be set to manual}
@note{Applies to Windows only.} |

| --- | --- |
| Default | n/a |
| Example | @code{}
dd_manual_resolution = 120
dd_manual_resolution = 59.95
@endcode |

dd_hdr_option

| Description | Perform additional HDR configuration for the display device.
@note{Applies to Windows only.} | |

| --- | --- | --- |
| Default | @code{}auto@endcode | |
| Example | @code{}
dd_hdr_option = disabled
@endcode | |
| Choices | disabled | Perform no additional configuration. |
| auto | Change HDR to the requested state from the client if the display supports it. | |

dd_wa_hdr_toggle_delay

| Description | When using virtual display device (VDD) for streaming, it might incorrectly display HDR color. Sunshine can try to mitigate this issue, by turning HDR off and then on again.
If the value is set to 0, the workaround is disabled (default). If the value is between 0 and 3000 milliseconds, Sunshine will turn off HDR, wait for the specified amount of time and then turn HDR on again. The recommended delay time is around 500 milliseconds in most cases.
DO NOT use this workaround unless you actually have issues with HDR as it directly impacts stream start time!
@note{This option works independently of dd_hdr_option}
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
0
@endcode |
| Example | @code{}
dd_wa_hdr_toggle_delay = 500
@endcode |

dd_config_revert_delay

| Description | Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated.
Main purpose is to provide a smoother transition when quickly switching between apps.
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}3000@endcode |
| Example | @code{}
dd_config_revert_delay = 1500
@endcode |

dd_config_revert_on_disconnect

| Description | When enabled, display configuration is reverted upon disconnect of all clients instead of app close or last session termination.
This can be useful for returning to physical usage of the host machine without closing the active app.
@warning{Some applications may not function properly when display configuration is changed while active.}
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}disabled@endcode |
| Example | @code{}
dd_config_revert_on_disconnect = enabled
@endcode |

dd_mode_remapping

| Description | Remap the requested resolution and FPS to another display mode.
Depending on the dd_resolution_option and
dd_refresh_rate_option values, the following mapping
groups are available:

text
`mixed` - both options are set to `auto`.
            
              `resolution_only` - only [dd_resolution_option](#dd_resolution_option) is set to `auto`.
            
            
              `refresh_rate_only` - only [dd_refresh_rate_option](#dd_refresh_rate_option) is set to `auto`.
            
        
        For each of those groups, a list of fields can be configured to perform remapping:
        
            
              `requested_resolution` - resolution that needs to be matched in order to use this remapping entry.
            
            `requested_fps` - FPS that needs to be matched in order to use this remapping entry.
            `final_resolution` - resolution value to be used if the entry was matched.
            `final_refresh_rate` - refresh rate value to be used if the entry was matched.
        
        If `requested_*` field is left empty, it will match **everything**.
        If `final_*` field is left empty, the original value will not be remapped and either a requested, manual
        or current value is used. However, at least one `final_*` must be set, otherwise the entry is considered
        invalid.
        @note{"Optimize game settings" must be enabled on client side for ANY entry with `resolution`
        field to be considered.}
        @note{First entry to be matched in the list is the one that will be used.}
        @tip{`requested_resolution` and `final_resolution` can be omitted for `refresh_rate_only` group.}
        @tip{`requested_fps` and `final_refresh_rate` can be omitted for `resolution_only` group.}
        @note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
dd_mode_remapping = {
"mixed": [],
"resolution_only": [],
"refresh_rate_only": []
}
@endcode |
| Example | @code{}
dd_mode_remapping = {
"mixed": [
{
"requested_fps": "60",
"final_refresh_rate": "119.95",
"requested_resolution": "1920x1080",
"final_resolution": "2560x1440"
},
{
"requested_fps": "60",
"final_refresh_rate": "120",
"requested_resolution": "",
"final_resolution": ""
}
],
"resolution_only": [
{
"requested_resolution": "1920x1080",
"final_resolution": "2560x1440"
}
],
"refresh_rate_only": [
{
"requested_fps": "60",
"final_refresh_rate": "119.95"
}
]
}@endcode |

max_bitrate

Description The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.
Default @code{}
text
0
        @endcode |

| Example | @code{}
max_bitrate = 5000
@endcode |

minimum_fps_target

Description Sunshine tries to save bandwidth when content on screen is static or a low framerate. Because many clients expect a constant stream of video frames, a certain amount of duplicate frames are sent when this happens. This setting controls the lowest effective framerate a stream can reach.
Default @code{}
text
0
        @endcode |  |

| Choices | 0 | Use half the stream's FPS as the minimum target. |
| 1-1000 | Specify your own value. The real minimum may differ from this value. | |

Network

upnp

Description Sunshine will attempt to open ports for streaming over the internet.
Default @code{}
text
disabled
        @endcode |

| Example | @code{}
upnp = enabled
@endcode |

address_family

Description Set the address family that Sunshine will use.
Default @code{}
text
ipv4
        @endcode |  |

| Example | @code{}
address_family = both
@endcode | |
| Choices | ipv4 | IPv4 only |
| both | IPv4+IPv6 | |

bind_address

| Description | Set the IP address to bind Sunshine to. This is useful when you have multiple network interfaces
and want to restrict Sunshine to a specific one. If not set, Sunshine will bind to all available
interfaces (0.0.0.0 for IPv4 or :: for IPv6).

text
**Note:** The address must be valid for the system and must match the address family
        being used. When using IPv6, you can specify an IPv6 address even with address_family set to "both". |

| --- | --- |
| Default | @code{}
(empty - bind to all interfaces)
@endcode |
| Example (IPv4) | @code{}
bind_address = 192.168.1.100
@endcode |
| Example (IPv6) | @code{}
bind_address = 2001:db8::1
@endcode |
| Example (Loopback) | @code{}
bind_address = 127.0.0.1
@endcode |

port

| Description | Set the family of ports used by Sunshine.
Changing this value will offset other ports as shown in config UI. |

| --- | --- |
| Default | @code{}
47989
@endcode |
| Range | 1029-65514 |
| Example | @code{}
port = 47989
@endcode |

origin_web_ui_allowed

Description The origin of the remote endpoint address that is not denied for HTTPS Web UI.
Default @code{}
text
lan
        @endcode |  |

| Example | @code{}
origin_web_ui_allowed = lan
@endcode | |
| Choices | pc | Only localhost may access the web ui |
| lan | Only LAN devices may access the web ui | |
| wan | Anyone may access the web ui | |

csrf_allowed_origins

| Description | Comma-separated list of additional allowed origins for CSRF protection. These origins will be
appended to the default allowed origins (localhost variants and the configured web UI port).
Requests from allowed origins can access state-changing API endpoints without CSRF tokens.

text
@attention{Only add origins you trust. Each origin must be a complete URL prefix
        including protocol and host (e.g., https://example.com). Port numbers are optional.} |

| --- | --- |
| Default | @code{}
(empty - uses built-in defaults: https://localhost, https://127.0.0.1, https://[::1],
with configured UI port variants)
@endcode |
| Example | @code{}
csrf_allowed_origins = https://myapp.local,https://custom.domain.com
@endcode |

external_ip

Description If no external IP address is given, Sunshine will attempt to automatically detect external ip-address.
Default Automatic
Example @code{}
text
external_ip = 123.456.789.12
        @endcode |

lan_encryption_mode

| Description | This determines when encryption will be used when streaming over your local network.
@warning{Encryption can reduce streaming performance, particularly on less powerful hosts and clients.} | |

| --- | --- | --- |
| Default | @code{}
0
@endcode | |
| Example | @code{}
lan_encryption_mode = 0
@endcode | |
| Choices | 0 | encryption will not be used |
| 1 | encryption will be used if the client supports it | |
| 2 | encryption is mandatory and unencrypted connections are rejected | |

wan_encryption_mode

| Description | This determines when encryption will be used when streaming over the Internet.
@warning{Encryption can reduce streaming performance, particularly on less powerful hosts and clients.} | |

| --- | --- | --- |
| Default | @code{}
1
@endcode | |
| Example | @code{}
wan_encryption_mode = 1
@endcode | |
| Choices | 0 | encryption will not be used |
| 1 | encryption will be used if the client supports it | |
| 2 | encryption is mandatory and unencrypted connections are rejected | |

ping_timeout

Description How long to wait, in milliseconds, for data from Moonlight before shutting down the stream.
Default @code{}
text
10000
        @endcode |

| Example | @code{}
ping_timeout = 10000
@endcode |

packetsize

| Description | Limit the packetsize to avoid fragmentation on a low MTU link.
@note{This helps avoid packet loss and micro-stutter on a layer 2 VPN with
clients that cannot configure this value, e.g. Moonlight for Android/iOS.
}
@tip{To discover the optimal value:

text
Send ping to the server with don't fragment flag (DF)
            Find the size of the largest replay, and subtract 16
            Monitor the traffic to ensure no fragmentation
        
        If using a VPN tunnel:
        
            Set MTU on the TUN/TAP interface, and
            Ensure no fragmentation both inside and outside the tunnel
            Max UDP size = MTU size - 28
            `packetsize` = max UDP size - 16
            Monitor the traffic to ensure no fragmentation
        
        Sample calculation for OpenVPN layer 2, using IPv4:
        
            1428 bytes for max ICMP/UDP size outside the tunnel
            Subtract the OpenVPN overhead: 24 bytes (may vary)
            1404 bytes for Ethernet inside the tunnel
            Subtract the Ethernet header: 14 bytes
            1390 bytes for MTU inside the tunnel
            Subtract the IPv4 header: 20 bytes
            Subtract the UDP header: 8 bytes
            1362 bytes for UDP payload
            Subtract: 16 bytes
            1346 bytes for `packetsize`
        
        }
        @warning{Reduce the bitrate when using low values.
        Values larger than 1456 require jumbo frames.
        } |

| --- | --- |
| Default | @code{}
0
@endcode |
| Range | 0, 200-65535 |
| Example | @code{}
packetsize = 1346
@endcode |

Config Files

file_apps

| Description | The application configuration file path. The file contains a JSON formatted list of applications that
can be started by Moonlight. |

| --- | --- |
| Default | @code{}
apps.json
@endcode |
| Example | @code{}
file_apps = apps.json
@endcode |

credentials_file

Description The file where user credentials for the UI are stored.
Default @code{}
text
sunshine_state.json
        @endcode |

| Example | @code{}
credentials_file = sunshine_state.json
@endcode |

log_path

| Description | The path where the current Sunshine log is stored. Each time Sunshine starts, up to five previous
logs are retained by appending .1 through .5 to this path. |

| --- | --- |
| Default | @code{}
sunshine.log
@endcode |
| Example | @code{}
log_path = sunshine.log
@endcode |

pkey

| Description | The private key used for the web UI and Moonlight client pairing. For best compatibility,
this should be an RSA-2048 private key.
@warning{Not all Moonlight clients support ECDSA keys or RSA key lengths other than 2048 bits.} |

| --- | --- |
| Default | @code{}
credentials/cakey.pem
@endcode |
| Example | @code{}
pkey = /dir/pkey.pem
@endcode |

cert

| Description | The certificate used for the web UI and Moonlight client pairing. For best compatibility,
this should have an RSA-2048 public key.
@warning{Not all Moonlight clients support ECDSA keys or RSA key lengths other than 2048 bits.} |

| --- | --- |
| Default | @code{}
credentials/cacert.pem
@endcode |
| Example | @code{}
cert = /dir/cert.pem
@endcode |

file_state

Description The file where current state of Sunshine is stored.
Default @code{}
text
sunshine_state.json
        @endcode |

| Example | @code{}
file_state = sunshine_state.json
@endcode |

Advanced

fec_percentage

| Description | Percentage of error correcting packets per data packet in each video frame.
@warning{Higher values can correct for more network packet loss,
but at the cost of increasing bandwidth usage.} |

| --- | --- |
| Default | @code{}
20
@endcode |
| Range | 1-255 |
| Example | @code{}
fec_percentage = 20
@endcode |

qp

| Description | Quantization Parameter. Some devices don't support Constant Bit Rate. For those devices, QP is used instead.
@warning{Higher value means more compression, but less quality.} |

| --- | --- |
| Default | @code{}
28
@endcode |
| Example | @code{}
qp = 28
@endcode |

min_threads

| Description | Minimum number of CPU threads used for encoding.
@note{Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually worth it to
gain the use of more CPU cores for encoding. The ideal value is the lowest value that can reliably encode
at your desired streaming settings on your hardware.} |

| --- | --- |
| Default | @code{}
2
@endcode |
| Example | @code{}
min_threads = 2
@endcode |

hevc_mode

| Description | Allows the client to request HEVC Main or HEVC Main10 video streams.
@warning{HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software
encoding.} | |

| --- | --- | --- |
| Default | @code{}
0
@endcode | |
| Example | @code{}
hevc_mode = 2
@endcode | |
| Choices | 0 | advertise support for HEVC based on encoder capabilities (recommended) |
| 1 | do not advertise support for HEVC | |
| 2 | advertise support for HEVC Main profile | |
| 3 | advertise support for HEVC Main and Main10 (HDR) profiles | |

av1_mode

| Description | Allows the client to request AV1 Main 8-bit or 10-bit video streams.
@warning{AV1 is more CPU-intensive to encode, so enabling this may reduce performance when using software
encoding.} | |

| --- | --- | --- |
| Default | @code{}
0
@endcode | |
| Example | @code{}
av1_mode = 2
@endcode | |
| Choices | 0 | advertise support for AV1 based on encoder capabilities (recommended) |
| 1 | do not advertise support for AV1 | |
| 2 | advertise support for AV1 Main 8-bit profile | |
| 3 | advertise support for AV1 Main 8-bit and 10-bit (HDR) profiles | |

capture

Description Force specific screen capture method.
Default Automatic.
text
Sunshine will use the first capture method available in the order of the table above. |  |

| Example | @code{}
capture = kms
@endcode | |
| Choices | nvfbc | Use NVIDIA Frame Buffer Capture to capture direct to GPU memory. This is usually the fastest method for
NVIDIA cards. NvFBC does not have native Wayland support and does not work with XWayland.
@note{Applies to Linux only.} |
| wlr | Capture for wlroots based Wayland compositors via wlr-screencopy-unstable-v1. It is possible to capture
virtual displays in e.g. Hyprland using this method.
@note{Applies to Linux only.} | |
| kms | DRM/KMS screen capture from the kernel. This requires that Sunshine has cap_sys_admin capability.
@note{Applies to Linux only.} | |
| kwin | Capture with KDE/KWin Wayland compositor via KDE screencasting.
@note{Applies to Linux only.} | |
| x11 | Uses XCB. This is the slowest and most CPU intensive so should be avoided if possible.
@note{Applies to FreeBSD and Linux only.} | |
| ddx | Use DirectX Desktop Duplication API to capture the display. This is well-supported on Windows machines.
@note{Applies to Windows only.} | |
| wgc | (beta feature) Use Windows.Graphics.Capture to capture the display.
@note{Applies to Windows only.}
@attention{This capture method is not compatible with the Sunshine service.} | |

encoder

Description Force a specific encoder.
Default Sunshine will use the first encoder that is available.
Example @code{}
text
encoder = nvenc
        @endcode |  |

| Choices | nvenc | For NVIDIA graphics cards |
| quicksync | For Intel graphics cards | |
| amdvce | For AMD graphics cards | |
| vaapi | Use VA-API (AMD, Intel) | |
| vulkan | Use Vulkan encoder (AMD, Intel, NVIDIA).
@note{Applies to Linux only.} | |
| software | Encoding occurs on the CPU | |

NVIDIA NVENC Encoder

nvenc_preset

| Description | NVENC encoder performance preset.
Higher numbers improve compression (quality at given bitrate) at the cost of increased encoding latency.
Recommended to change only when limited by network or decoder, otherwise similar effect can be accomplished
by increasing bitrate.
@note{This option only applies when using NVENC encoder.} | |

| --- | --- | --- |
| Default | @code{}
1
@endcode | |
| Example | @code{}
nvenc_preset = 1
@endcode | |
| Choices | 1 | P1 (fastest) |
| 2 | P2 | |
| 3 | P3 | |
| 4 | P4 | |
| 5 | P5 | |
| 6 | P6 | |
| 7 | P7 (slowest) | |

nvenc_twopass

| Description | Enable two-pass mode in NVENC encoder.
This allows to detect more motion vectors, better distribute bitrate across the frame and more strictly
adhere to bitrate limits. Disabling it is not recommended since this can lead to occasional bitrate
overshoot and subsequent packet loss.
@note{This option only applies when using NVENC encoder.} | |

| --- | --- | --- |
| Default | @code{}
quarter_res
@endcode | |
| Example | @code{}
nvenc_twopass = quarter_res
@endcode | |
| Choices | disabled | One pass (fastest) |
| quarter_res | Two passes, first pass at quarter resolution (faster) | |
| full_res | Two passes, first pass at full resolution (slower) | |

nvenc_spatial_aq

| Description | Assign higher QP values to flat regions of the video.
Recommended to enable when streaming at lower bitrates.
@note{This option only applies when using NVENC encoder.}
@warning{Enabling this option may reduce performance.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
nvenc_spatial_aq = disabled
@endcode |

nvenc_vbv_increase

| Description | Single-frame VBV/HRD percentage increase.
By default Sunshine uses single-frame VBV/HRD, which means any encoded video frame size is not expected to
exceed requested bitrate divided by requested frame rate. Relaxing this restriction can be beneficial and
act as low-latency variable bitrate, but may also lead to packet loss if the network doesn't have buffer
headroom to handle bitrate spikes. Maximum accepted value is 400, which corresponds to 5x increased
encoded video frame upper size limit.
@note{This option only applies when using NVENC encoder.}
@warning{Can lead to network packet loss.} |

| --- | --- |
| Default | @code{}
0
@endcode |
| Range | 0-400 |
| Example | @code{}
nvenc_vbv_increase = 0
@endcode |

nvenc_realtime_hags

| Description | Use realtime gpu scheduling priority in NVENC when hardware accelerated gpu scheduling (HAGS) is enabled
in Windows. Currently, NVIDIA drivers may freeze in encoder when HAGS is enabled, realtime priority is used
and VRAM utilization is close to maximum. Disabling this option lowers the priority to high, sidestepping
the freeze at the cost of reduced capture performance when the GPU is heavily loaded.
@note{This option only applies when using NVENC encoder.}
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
nvenc_realtime_hags = enabled
@endcode |

nvenc_split_encode

| Description | Split the encoding of each video frame over multiple NVENC hardware units.
Significantly reduces encoding latency with a marginal compression efficiency penalty.
This option is ignored if your GPU has a singular NVENC unit.
@note{This option only applies when using NVENC encoder with HEVC or AV1.}
@note{Applies to Windows only.} | |

| --- | --- | --- |
| Default | @code{}
driver_decides
@endcode | |
| Example | @code{}
nvenc_split_encode = driver_decides
@endcode | |
| Choices | disabled | Disabled |
| driver_decides | The NVIDIA driver will automatically enable split frame encoding when the following conditions are met: 2+ NVENC units, resolution is at least 4K, and the preset is P1-P4. | |
| enabled | Enabled | |

nvenc_latency_over_power

| Description | Adaptive P-State algorithm which NVIDIA drivers employ doesn't work well with low latency streaming,
so Sunshine requests high power mode explicitly.
@note{This option only applies when using NVENC encoder.}
@warning{Disabling this is not recommended since this can lead to significantly increased encoding latency.}
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
nvenc_latency_over_power = enabled
@endcode |

nvenc_opengl_vulkan_on_dxgi

| Description | Sunshine can't capture fullscreen OpenGL and Vulkan programs at full frame rate unless they present on
top of DXGI. With this option enabled Sunshine changes global Vulkan/OpenGL present method to
"Prefer layered on DXGI Swapchain". This is system-wide setting that is reverted on Sunshine program exit.
@note{This option only applies when using NVENC encoder.}
@note{Applies to Windows only.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
nvenc_opengl_vulkan_on_dxgi = enabled
@endcode |

nvenc_h264_cavlc

| Description | Prefer CAVLC entropy coding over CABAC in H.264 when using NVENC.
CAVLC is outdated and needs around 10% more bitrate for same quality, but provides slightly faster
decoding when using software decoder.
@note{This option only applies when using H.264 format with the
NVENC encoder.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
nvenc_h264_cavlc = disabled
@endcode |

Intel QuickSync Encoder

qsv_preset

| Description | The encoder preset to use.
@note{This option only applies when using quicksync encoder.} | |

| --- | --- | --- |
| Default | @code{}
medium
@endcode | |
| Example | @code{}
qsv_preset = medium
@endcode | |
| Choices | veryfast | fastest (lowest quality) |
| faster | faster (lower quality) | |
| fast | fast (low quality) | |
| medium | medium (default) | |
| slow | slow (good quality) | |
| slower | slower (better quality) | |
| veryslow | slowest (best quality) | |

qsv_coder

| Description | The entropy encoding to use.
@note{This option only applies when using H.264 with the quicksync
encoder.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
qsv_coder = auto
@endcode | |
| Choices | auto | let ffmpeg decide |
| cabac | context adaptive binary arithmetic coding - higher quality | |
| cavlc | context adaptive variable-length coding - faster decode | |

qsv_slow_hevc

| Description | This options enables use of HEVC on older Intel GPUs that only support low power encoding for H.264.
@note{This option only applies when using quicksync encoder.}
@caution{Streaming performance may be significantly reduced when this option is enabled.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
qsv_slow_hevc = disabled
@endcode |

AMD AMF Encoder

amd_usage

| Description | The encoder usage profile is used to set the base set of encoding parameters.
@note{This option only applies when using amdvce encoder.}
@note{The other AMF options that follow will override a subset of the settings applied by your usage
profile, but there are hidden parameters set in usage profiles that cannot be overridden elsewhere.} | |

| --- | --- | --- |
| Default | @code{}
ultralowlatency
@endcode | |
| Example | @code{}
amd_usage = ultralowlatency
@endcode | |
| Choices | transcoding | transcoding (slowest) |
| webcam | webcam (slow) | |
| lowlatency_high_quality | low latency, high quality (fast) | |
| lowlatency | low latency (faster) | |
| ultralowlatency | ultra low latency (fastest) | |

amd_rc

| Description | The encoder rate control.
@note{This option only applies when using amdvce encoder.}
@warning{The vbr_latency option generally works best, but some bitrate overshoots may still occur.
Enabling HRD allows all bitrate based rate controls to better constrain peak bitrate, but may result in
encoding artifacts depending on your card.} | |

| --- | --- | --- |
| Default | @code{}
vbr_latency
@endcode | |
| Example | @code{}
amd_rc = vbr_latency
@endcode | |
| Choices | cqp | constant qp mode |
| cbr | constant bitrate | |
| vbr_latency | variable bitrate, latency constrained | |
| vbr_peak | variable bitrate, peak constrained | |

amd_enforce_hrd

| Description | Enable Hypothetical Reference Decoder (HRD) enforcement to help constrain the target bitrate.
@note{This option only applies when using amdvce encoder.}
@warning{HRD is known to cause encoding artifacts or negatively affect encoding quality on certain cards.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
amd_enforce_hrd = disabled
@endcode |

amd_quality

| Description | The quality profile controls the tradeoff between speed and quality of encoding.
@note{This option only applies when using amdvce encoder.} | |

| --- | --- | --- |
| Default | @code{}
balanced
@endcode | |
| Example | @code{}
amd_quality = balanced
@endcode | |
| Choices | speed | prefer speed |
| balanced | balanced | |
| quality | prefer quality | |

amd_preanalysis

| Description | Preanalysis can increase encoding quality at the cost of latency.
@note{This option only applies when using amdvce encoder.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
amd_preanalysis = disabled
@endcode |

amd_vbaq

| Description | Variance Based Adaptive Quantization (VBAQ) can increase subjective visual quality by prioritizing
allocation of more bits to smooth areas compared to more textured areas.
@note{This option only applies when using amdvce encoder.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
amd_vbaq = enabled
@endcode |

amd_coder

| Description | The entropy encoding to use.
@note{This option only applies when using H.264 with the amdvce
encoder.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
amd_coder = auto
@endcode | |
| Choices | auto | let ffmpeg decide |
| cabac | context adaptive binary arithmetic coding - faster decode | |
| cavlc | context adaptive variable-length coding - higher quality | |

VideoToolbox Encoder

vt_coder

| Description | The entropy encoding to use.
@note{This option only applies when using macOS.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
vt_coder = auto
@endcode | |
| Choices | auto | let ffmpeg decide |
| cabac | context adaptive binary arithmetic coding - faster decode | |
| cavlc | context adaptive variable-length coding - higher quality | |

vt_software

| Description | Force Video Toolbox to use software encoding.
@note{This option only applies when using macOS.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
vt_software = auto
@endcode | |
| Choices | auto | let ffmpeg decide |
| disabled | disable software encoding | |
| allowed | allow software encoding | |
| forced | force software encoding | |

vt_realtime

| Description | Realtime encoding.
@note{This option only applies when using macOS.}
@warning{Disabling realtime encoding might result in a delayed frame encoding or frame drop.} |

| --- | --- |
| Default | @code{}
enabled
@endcode |
| Example | @code{}
vt_realtime = enabled
@endcode |

VA-API Encoder

vaapi_blbrc

| Description | Block level based bitrate control (BLBRC) can assign different bitrate on a per-block basis. May improve quality on supported devices.
@note{This option only applies when using the VA-API encoder.} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
vaapi_blbrc = enabled
@endcode |

vaapi_quality

| Description | The quality profile controls the tradeoff between speed and quality of encoding.
@note{This option only applies when using the VA-API encoder.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
vaapi_quality = auto
@endcode | |
| Choices | auto | driver default quality |
| speed | prefer speed | |
| balanced | balanced | |
| quality | prefer quality | |

vaapi_rc

| Description | The encoder rate control.
@note{This option only applies when using the VA-API encoder.}
@warning{The automatic setting may override the driver-default rate control method to VBR and force vaapi_strict_rc_buffer enabled on certain configurations. Selecting another rate control manually will override this behaviour.} | |

| --- | --- | --- |
| Default | @code{}
auto
@endcode | |
| Example | @code{}
vaapi_rc = vbr
@endcode | |
| Choices | auto | driver default (or whitelisted override) |
| avbr | average variable bitrate | |
| cbr | constant bitrate | |
| cqp | constant qp mode | |
| icq | intelligent qp mode | |
| qvbr | quality-defined variable bitrate | |
| vbr | variable bitrate | |

vaapi_strict_rc_buffer

| Description | Enabling this option can avoid dropped frames over the network during scene changes, but video quality may
be reduced during motion.
@note{This option only applies for H.264 and HEVC when using VA-API encoder on AMD GPUs (or when overriding the default rate control on other devices).} |

| --- | --- |
| Default | @code{}
disabled
@endcode |
| Example | @code{}
vaapi_strict_rc_buffer = enabled
@endcode |

Vulkan Encoder

vk_tune

| Description | Encoder tuning preset. Low latency modes reduce encoding delay at the cost of quality.
@note{This option only applies when using Vulkan encoder.} | |

| --- | --- | --- |
| Default | @code{}
2
@endcode | |
| Example | @code{}
vk_tune = 1
@endcode | |
| Options | 0 (default) | Let the driver decide |
| | 1 (hq) | High Quality |
| | 2 (ll) | Low Latency |
| | 3 (ull) | Ultra Low Latency |
| | 4 (lossless) | Lossless |

vk_rc_mode

| Description | Rate control mode for encoding. Auto lets the driver decide.
@note{This option only applies when using Vulkan encoder.} | |

| --- | --- | --- |
| Default | @code{}
2
@endcode | |
| Example | @code{}
vk_rc_mode = 4
@endcode | |
| Options | 0 | Auto (driver decides) |
| | 1 | CQP (Constant QP) |
| | 2 | CBR (Constant Bitrate) |
| | 4 | VBR (Variable Bitrate) |

Software Encoder

sw_preset

| Description | The encoder preset to use.
@note{This option only applies when using software encoder.}
@note{From FFmpeg.

text
A preset is a collection of options that will provide a certain encoding speed to compression ratio. A slower
        preset will provide better compression (compression is quality per filesize). This means that, for example, if
        you target a certain file size or constant bit rate, you will achieve better quality with a slower preset.
        Similarly, for constant quality encoding, you will simply save bitrate by choosing a slower preset.
        
        
        Use the slowest preset that you have patience for.} |  |

| --- | --- | --- |
| Default | @code{}
superfast
@endcode | |
| Example | @code{}
sw_preset = superfast
@endcode | |
| Choices | ultrafast | fastest |
| superfast | | |
| veryfast | | |
| faster | | |
| fast | | |
| medium | | |
| slow | | |
| slower | | |
| veryslow | slowest | |

sw_tune

| Description | The tuning preset to use.
@note{This option only applies when using software encoder.}
@note{From FFmpeg.

text
You can optionally use -tune to change settings based upon the specifics of your input.
        } |  |

| --- | --- | --- |
| Default | @code{}
zerolatency
@endcode | |
| Example | @code{}
sw_tune = zerolatency
@endcode | |
| Choices | film | use for high quality movie content; lowers deblocking |
| animation | good for cartoons; uses higher deblocking and more reference frames | |
| grain | preserves the grain structure in old, grainy film material | |
| stillimage | good for slideshow-like content | |
| fastdecode | allows faster decoding by disabling certain filters | |
| zerolatency | good for fast encoding and low-latency streaming | |

Previous Next
Legal App Examples

[TOC]


File: docs/contributing.md

Contributing

Read our contribution guide in our organization level
docs.

Tool Description
CLion Recommended IDE for C and C++ development. Free for non-commercial use.

Project Patterns

Web UI

  • The Web UI uses Vite as its build system.
  • The HTML pages used by the Web UI are found in ./src_assets/common/assets/web.
  • EJS is used as a templating system for the pages
    (check template_header.html and template_header_main.html).
  • The Style System is provided by Bootstrap.
  • Icons are provided by Lucide and Simple Icons.
  • The JS framework used by the more interactive pages is Vue.js.

Building

@tabs{
@tab{CMake | bash cmake -B build -G Ninja -S . --target web-ui ninja -C build web-ui }
@tab{Manual | bash npm run dev }
}

Localization

Sunshine and related LizardByte projects are being localized into various languages.
The default language is en (English).

@admonition{Community | We are looking for language coordinators to help approve translations.
The goal is to have the bars above filled with green!
If you are interested, please reach out to us on our Discord server.}

CrowdIn

The translations occur on CrowdIn.
Anyone is free to contribute to the localization there.

Translation Basics

  • The brand names LizardByte and Sunshine should never be translated.
  • Other brand names should never be translated. Examples include AMD, Intel, and NVIDIA.

CrowdIn Integration

How does it work?

When a change is made to Sunshine source code, a workflow generates new translation templates
that get pushed to CrowdIn automatically.

When translations are updated on CrowdIn, a push gets made to the l10n_master branch and a PR is made against the
master branch. Once the PR is merged, all updated translations are part of the project and will be included in the
next release.

Extraction

Web UI

Sunshine uses Vue I18n for localizing the UI.
The following is a simple example of how to use it.

  • Add the string to the ./src_assets/common/assets/web/public/assets/locale/en.json file, in English.

    json
    {
     "index": {
       "welcome": "Hello, Sunshine!"
     }
    }

    [!NOTE]
    The JSON keys should be sorted alphabetically. You can use jsonabc
    to sort the keys.

    [!IMPORTANT]
    Due to the integration with Crowdin, it is important to only add strings to the en.json file,
    and to not modify any other language files. After the PR is merged, the translations can take place
    on CrowdIn. Once the translations are complete, a PR will be made
    to merge the translations into Sunshine.

  • Use the string in the Vue component.

    html
    <template>
      
        {{ $t('index.welcome') }}
      
    </template>

    [!TIP]
    More formatting examples can be found in the
    Vue I18n guide.

C++

There should be minimal cases where strings need to be extracted from C++ source code; however it may be necessary in
some situations. For example the system tray icon could be localized as it is user interfacing.

  • Wrap the string to be extracted in a function as shown.
    cpp
    #include 
    #include <string>
    
    std::string msg = boost::locale::translate("Hello world!");

[!TIP]
More examples can be found in the documentation for
boost locale.

[!WARNING]
The below is for information only. Contributors should never include manually updated template files, or
manually compiled language files in Pull Requests.

Strings are automatically extracted from the code to the locale/sunshine.po template file. The generated file is
used by CrowdIn to generate language specific template files. The file is generated using the
.github/workflows/localize.yml workflow and is run on any push event into the master branch. Jobs are only run if
any of the following paths are modified.

yaml
- 'src/**'

When testing locally, it may be desirable to manually extract, initialize, update, and compile strings. Python and
uv are required for this, along with the Python dependencies in the Sunshine pyproject.toml. From the repository
root, install these with the following command.

bash
uv sync --locked

Additionally, xgettext must be installed.

  • Extract, initialize, and update

    bash
    uv run --locked --no-sync lb-localize --root-dir . --extract --init --update
  • Compile

    bash
    uv run --locked --no-sync lb-localize --root-dir . --compile

[!IMPORTANT]
Due to the integration with CrowdIn, it is important to not include any extracted or compiled files in
Pull Requests. The files are automatically generated and updated by the workflow. Once the PR is merged, the
translations can take place on CrowdIn. Once the translations are
complete, a PR will be made to merge the translations into Sunshine.

Testing

Clang Format

Source code is tested against the .clang-format file for linting errors.

From the repository root, apply clang-format locally with the installed lizardbyte-common script. This will modify
files in place.

bash
uv sync --locked
uv run --locked --no-sync lb-update-clang-format

Unit Testing

Sunshine uses Google Test for unit testing. Google Test is included in the
repo as a submodule. The test sources are located in the ./tests directory.

The tests need to be compiled into an executable, and then run. The tests are built using the normal build process, but
can be disabled by setting the BUILD_TESTS CMake option to OFF.

To run the tests, execute the following command.

bash
./build/tests/test_sunshine

To see all available options, run the tests with the --help flag.

bash
./build/tests/test_sunshine --help

[!TIP]
See the googletest FAQ for more information on how to use Google Test.

We use gcovr to generate code coverage reports,
and Codecov to analyze the reports for all PRs and commits.

Codecov will fail a PR if the total coverage is reduced too much, or if not enough of the diff is covered by tests.
In some cases, the code cannot be covered when running the tests inside of GitHub runners. For example, any test that
needs access to the GPU will not be able to run. In these cases, the coverage can be omitted by adding comments to the
code. See the gcovr documentation for
more information.

Even if your changes cannot be covered in the CI, we still encourage you to write the tests for them. This will allow
maintainers to run the tests locally.

Previous Next
Building Source Code

[TOC]


File: docs/gamestream_migration.md

GameStream Migration

Nvidia announced that their GameStream service for Nvidia Games clients will be discontinued in February 2023.
Luckily, Sunshine performance is now equal to or better than Nvidia GameStream.

Migration

We have developed a simple migration tool to help you migrate your GameStream games and apps to Sunshine automatically.
Please check out our GSMS project if you're interested in an automated
migration option. GSMS offers the ability to migrate your custom and auto-detected games and apps. The
working directory, command, and image are all set in Sunshine's apps.json file. The box-art image is also copied
to a specified directory.

Internet Streaming

If you are using the Moonlight Internet Hosting Tool, you can remove it from your system when you migrate to Sunshine.
To stream over the Internet with Sunshine and a UPnP-capable router, enable the UPnP option in the Sunshine Web UI.

[!NOTE]
Running Sunshine together with versions of the Moonlight Internet Hosting Tool prior to v5.6 will cause UPnP
port forwarding to become unreliable. Either uninstall the tool entirely or update it to v5.6 or later.

Limitations

Sunshine does have some limitations, as compared to Nvidia GameStream.

  • Automatic game/application list.
  • Changing game settings automatically to optimize streaming.
Previous Next
Third-party Packages Legal

[TOC]


File: docs/getting_started.md

Getting Started

The recommended method for running Sunshine is to use the binaries included in the
latest release, unless otherwise specified.

Pre-releases are also available. These should be considered beta,
and release artifacts may be missing when merging changes on a faster cadence.

Binaries

Binaries of Sunshine are created for each release. They are available for FreeBSD, Linux, macOS, and Windows.
Binaries can be found in the latest release.

[!NOTE]
Some third party packages also exist.
See Third Party Packages for more information.
No support will be provided for third party packages!

Install

Docker

[!WARNING]
The Docker images are not recommended for most users.

Docker images are available on Dockerhub.io
and ghcr.io.

See Docker for more information.

FreeBSD

Install

  1. Download the appropriate package for your architecture

    Architecture Package
    amd64/x86_64 Sunshine-FreeBSD-14.4-amd64.pkg
    arm64/aarch64 Sunshine-FreeBSD-14.4-aarch64.pkg
  2. Open terminal and run the following command.

    sh
    sudo pkg install ./Sunshine-FreeBSD-14.4-{arch}.pkg

Uninstall

sh
sudo pkg delete Sunshine

Linux

CUDA Compatibility

CUDA is used for NVFBC capture.

[!NOTE]
See CUDA GPUS to cross-reference Compute Capability to your GPU.
The table below applies to packages provided by LizardByte. If you use an official LizardByte package, then you do not
need to install CUDA.

CUDA Version Min Driver CUDA Compute Capabilities Package
13.1.1 590.48.01 50;52;60;61;62;70;72;75;80;86;87;89;90;100;101;103;120;121 sunshine.AppImage
sunshine-ubuntu-22.04-{arch}.deb
sunshine-ubuntu-24.04-{arch}.deb
sunshine-debian-trixie-{arch}.deb
sunshine_{arch}.flatpak
Sunshine (copr - Fedora)
Sunshine (copr - OpenSUSE)
sunshine.pkg.tar.zst

AppImage

[!CAUTION]
Use distro-specific packages instead of the AppImage if they are available.
AppImage does not support KMS capture.

[!NOTE]
The AppImage is built on Ubuntu 22.04, which requires glibc 2.35 or newer and libstdc++ 3.4.11 or newer.

Install

  1. Download sunshine.AppImage
    into your home directory.
    bash
    cd ~
    wget https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine.AppImage
  2. Open terminal and run the following command.
    bash
    ./sunshine.AppImage --install

Run

bash
./sunshine.AppImage --install && ./sunshine.AppImage

Uninstall

bash
./sunshine.AppImage --remove

ArchLinux

[!CAUTION]
Use AUR packages at your own risk.

Install Prebuilt Packages

Follow the instructions at LizardByte's pacman-repo to add
the repository. Then run the following command.

bash
pacman -S sunshine

Install PKGBUILD Archive

Open terminal and run the following command.

bash
wget https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine.pkg.tar.gz
tar -xvf sunshine.pkg.tar.gz
cd sunshine

# install optional dependencies
pacman -S cuda  # Nvidia GPU encoding support
pacman -S libva-mesa-driver  # AMD GPU encoding support

makepkg -si

Uninstall

bash
pacman -R sunshine

Debian/Ubuntu

Install

Download sunshine-{distro}-{distro-version}-{arch}.deb and run the following command.

bash
sudo dpkg -i ./sunshine-{distro}-{distro-version}-{arch}.deb

[!NOTE]
The {distro-version} is the version of the distro we built the package on. The {arch} is the
architecture of your operating system.

[!TIP]
You can double-click the deb file to see details about the package and begin installation.

Uninstall

bash
sudo apt remove sunshine

Fedora/OpenSUSE

[!TIP]
The package name is case-sensitive.

Install (GitHub releases)

Download Sunshine-{version}.{distro+version}.{arch}.rpm and run the following command.

bash
sudo dnf install ./Sunshine-{version}.{distro}.{arch}.rpm

[!NOTE]
The {distro+version} is the distro and distro version of the distro we built the package on. The {arch} is the
architecture of your operating system.

[!TIP]
You can double-click the rpm file to see details about the package and begin installation.

Uninstall

bash
sudo dnf remove sunshine

Install (Copr)

[!IMPORTANT]
Stable builds are only available if the Sunshine release was made after the Fedora version release.
Because of this, it is often recommended to use the beta copr; however, you do not need to regularly update.
This could lead to annoyances in rare cases where there may be a breaking change.

  1. Enable copr repository.

    bash
    sudo dnf copr enable lizardbyte/stable

    or

    bash
    sudo dnf copr enable lizardbyte/beta
  2. Install the package.

    bash
    sudo dnf install Sunshine

Uninstall

bash
sudo dnf remove Sunshine

Flatpak

[!CAUTION]
Use distro-specific packages instead of the Flatpak if they are available.
Flatpak does not support KMS capture.

Using this package requires that you have Flatpak installed.

Download (local option)

  1. Download sunshine_{arch}.flatpak and run the following command.

    [!NOTE]
    Replace {arch} with your system architecture.

Install (system level)

Flathub

bash
flatpak install --system flathub dev.lizardbyte.app.Sunshine

Local

bash
flatpak install --system ./sunshine_{arch}.flatpak

Install (user level)

Flathub

bash
flatpak install --user flathub dev.lizardbyte.app.Sunshine

Local

bash
flatpak install --user ./sunshine_{arch}.flatpak

Additional installation (required)

bash
flatpak run --command=additional-install.sh dev.lizardbyte.app.Sunshine

Run with NVFBC capture (X11 Only) or XDG Portal (Wayland Only)

bash
flatpak run dev.lizardbyte.app.Sunshine

Uninstall

bash
flatpak run --command=remove-additional-install.sh dev.lizardbyte.app.Sunshine
flatpak uninstall --delete-data dev.lizardbyte.app.Sunshine

Homebrew

[!IMPORTANT]
The Homebrew package is experimental on Linux.

This package requires that you have Homebrew installed.

Install

bash
brew update
brew upgrade
brew tap LizardByte/homebrew
brew install sunshine

Uninstall

bash
brew uninstall sunshine

[!TIP]
For beta you can replace sunshine with sunshine-beta in the above commands.

macOS

[!IMPORTANT]
Sunshine on macOS is experimental. Gamepads do not work.

DMG

Install

  1. Download and install based on your architecture:

    Architecture Package
    arm64 (Apple Silicon) Sunshine-macOS-arm64.dmg
    x86_64 (Intel) Sunshine-macOS-x86_64.dmg
  2. Open the downloaded .dmg file.

  3. Drag Sunshine.app into the Applications folder.

  4. Eject the disk image.

Uninstall

  1. Quit Sunshine if it is running.
  2. Open Finder, navigate to Applications, and drag Sunshine.app to the Trash.

Homebrew

This package requires that you have Homebrew installed.

Install

bash
brew update
brew upgrade
brew tap LizardByte/homebrew
brew install sunshine

Uninstall

bash
brew uninstall sunshine

[!TIP]
For beta you can replace sunshine with sunshine-beta in the above commands.

Windows

[!NOTE]
Sunshine supports ARM64 on Windows; however, this should be considered experimental. This version does not properly
support GPU scheduling and any hardware acceleration.

[!CAUTION]
The msi installer is preferred moving forward. Before using a different type of installer, you should manually
uninstall the previous installation.

  1. Download and install based on your architecture:

    Architecture Installer
    AMD64/x64 (Intel/AMD) Sunshine-Windows-AMD64-installer.msi
    ARM64 Sunshine-Windows-ARM64-installer.msi

[!TIP]
Installer logs can be found in the following directory:
%%TEMP%/Sunshine/logs/install/

[!CAUTION]
You should carefully select or unselect the options you want to install. Do not blindly install or
enable features.

To uninstall, find Sunshine in the list here and select "Uninstall" from the
overflow menu. Different versions of Windows may provide slightly different steps for uninstall.

Standalone (lite version)

[!WARNING]
By using this package instead of the installer, performance will be reduced. This package is not
recommended for most users. No support will be provided!

  1. Download and extract based on your architecture:

    Architecture Installer
    AMD64/x64 (Intel/AMD) Sunshine-Windows-AMD64-lite.zip
    ARM64 Sunshine-Windows-ARM64-lite.zip
  2. Open command prompt as administrator

  3. Firewall rules

    Install:

    bash
    cd /d {path to extracted directory}
    scripts/add-firewall-rule.bat

    Uninstall:

    bash
    cd /d {path to extracted directory}
    scripts/delete-firewall-rule.bat
  4. Windows service

    Install:

    bash
    cd /d {path to extracted directory}
    scripts/install-service.bat
    scripts/autostart-service.bat

    Uninstall:

    bash
    cd /d {path to extracted directory}
    scripts/uninstall-service.bat

Initial Setup

After installation, some initial setup is required.

FreeBSD

Virtual Input Devices

[!IMPORTANT]
To use virtual input devices (keyboard, mouse, gamepads), you must add your user to the input group.

The installation process creates the input group and configures permissions for /dev/uinput.
To allow your user to create virtual input devices, run:

bash
pw groupmod input -m $USER

After adding yourself to the group, log out and log back in for the changes to take effect.

Linux

Services

Start once

bash
systemctl --user start app-dev.lizardbyte.app.Sunshine

Start on boot

bash
systemctl --user --now enable app-dev.lizardbyte.app.Sunshine

[!NOTE]
The service has been renamed to "app-dev.lizardbyte.app.Sunshine" in order to increase compatibility with
XDG Desktop Portal, but it is also aliased to "sunshine.service" for convenience.

macOS

The first time you start Sunshine, you will be asked to grant access to screen recording and your microphone.

Sunshine supports native system audio capture on macOS 14.0 (Sonoma) and newer via Appleโ€™s Audio Tap API.
To use it, simply leave the Audio Sink setting blank.

If you prefer to manage your own loopback device, you can still use
Soundflower or
BlackHole
and enter its device name in the audio_sink field.

[!NOTE]
Command Keys are not forwarded by Moonlight. Right Option-Key is mapped to CMD-Key.

[!CAUTION]
Gamepads are not currently supported.

Windows

Sunshine uses libvirtualhid for virtual gamepads on Windows. You must install the
Virtual HID Driver separately for full virtual gamepad
support. ViGEmBus is detected only as a limited fallback for Xbox 360 and DualShock 4 gamepads when libvirtualhid is
unavailable.

Compared with the ViGEmBus fallback, Virtual HID Driver can create Xbox One, Xbox Series, DualSense, Nintendo Switch
Pro, and Generic gamepads in addition to Xbox 360 and DualShock 4. It can also expose controller-specific features such
as motion, touchpads, LEDs, and adaptive triggers when supported. Virtual HID Driver is actively developed and
supported by the LizardByte team.

The Virtual HID Driver also requires an active machine license. Sunshine shows the current license status and actions
on the Web UI Troubleshooting page and in the Virtual HID Driver system tray submenu. When Sunshine starts on an
unactivated machine, select its tray notification to open the activation and purchase options in the Web UI.

After installing or updating virtual input drivers, it is recommended to restart your computer.

Usage

Basic usage

If Sunshine is not installed/running as a service, then start Sunshine with the following command, unless a start
command is listed in the specified package install instructions above.

[!NOTE]
A service is a process that runs in the background. This is the default when installing Sunshine from the
Windows installer. Running multiple instances of Sunshine is not advised.

bash
sunshine

Specify config file

bash
sunshine <directory of conf file>/sunshine.conf

[!NOTE]
This step is optional, you do not need to specify a config file.
If no config file is entered, the default location will be used.
The configuration file specified will be created if it doesn't exist.

Start Sunshine over SSH (Linux/X11)

Assuming you are already logged into the host, you can use this command

bash
ssh @ 'export DISPLAY=:0; sunshine'

If you are logged into the host with only a tty (teletypewriter), you can use startx to start the X server prior to
executing Sunshine. You nay need to add sleep between startx and sunshine to allow more time for the display to
be ready.

bash
ssh @ 'startx &; export DISPLAY=:0; sunshine'

[!TIP]
You could also use the ~/.bash_profile or ~/.bashrc files to set up the DISPLAY variable.

@seealso{See Remote SSH Headless Setup
on how to set up a headless streaming server without autologin and dummy plugs (X11 + NVidia GPUs)}

Configuration

Sunshine is configured via the web ui, which is available on https://localhost:47990
by default. You may replace localhost with your internal ip address.

[!NOTE]
Ignore any warning given by your browser about "insecure website". This is due to the SSL certificate
being self-signed.

[!CAUTION]
If running for the first time, make sure to note the username and password that you created.

  1. Change the web-ui to your desired theme, using the dropdown menu in the navbar.

  2. Add games and applications.

  3. Adjust any configuration settings as needed. You can search for options in the search bar.

  4. Find Moonlight clients and other tools for Sunshine in the Featured Apps tab.

  5. In Moonlight, you may need to add the PC manually.

  6. When Moonlight requests for you insert the pin:

    • Login to the web-ui
    • Go to "PIN" in the Navbar
    • Type in your PIN and press Enter, and enter a name of your choosing for the device.
      You should get a Success Message!
    • In Moonlight, select one of the Applications listed
  7. If you run into issues, logs are available in the Troubleshooting tab.
    You can navigate through each warning/error message for clues to the issue.

Arguments

To get a list of available arguments, run the following command.

@tabs{
@tab{ General | bash sunshine --help }
@tab{ AppImage | bash ./sunshine.AppImage --help }
@tab{ Flatpak | bash flatpak run --command=sunshine dev.lizardbyte.app.Sunshine --help }
}

Shortcuts

All shortcuts start with Ctrl+Alt+Shift, just like Moonlight.

  • Ctrl+Alt+Shift+N: Hide/Unhide the cursor (This may be useful for Remote Desktop Mode for Moonlight)
  • Ctrl+Alt+Shift+F1/F12: Switch to different monitor for Streaming

Application List

  • Applications should be configured via the web UI
  • A basic understanding of working directories and commands is required
  • You can use Environment variables in place of values
  • $(HOME) will be replaced by the value of $HOME
  • $$ will be replaced by $, e.g. $$(HOME) will be become $(HOME)
  • env - Adds or overwrites Environment variables for the commands/applications run by Sunshine.
    This can only be changed by modifying the apps.json file directly.

Considerations

  • On Windows, Sunshine uses the Desktop Duplication API which only supports capturing from the GPU used for display.
    If you want to capture and encode on the eGPU, connect a display or HDMI dummy display dongle to it and run the games
    on that display.

  • When an application is started, if there is an application already running, it will be terminated.

  • If any of the prep-commands fail, starting the application is aborted.

  • When the application has been shutdown, the stream shuts down as well.

    • For example, if you attempt to run steam as a cmd instead of detached the stream will immediately fail.
      This is due to the method in which the steam process is executed. Other applications may behave similarly.
    • This does not apply to detached applications.
  • The "Desktop" app works the same as any other application except it has no commands. It does not start an application,
    instead it simply starts a stream. If you removed it and would like to get it back, just add a new application with
    the name "Desktop" and "desktop.png" as the image path.

  • For the Linux flatpak you must prepend commands with flatpak-spawn --host.

  • If inputs (mouse, keyboard, gamepads...) aren't working after connecting:

    • On FreeBSD/Linux, add the user running sunshine to the input group.
  • The FreeBSD version of Sunshine is missing some features that are present on Linux.
    The following are known limitations.

    • Only X11 and Wayland capture are supported
    • Gamepads use libvirtualhid's uinput backend, so descriptor-driven features such as motion, touchpad input,
      battery state, RGB LEDs, adaptive triggers, and raw HID output reports are unavailable

HDR Support

Streaming HDR content is officially supported on Windows hosts and experimentally supported for Linux hosts.

  • General HDR support information and requirements:

    • HDR must be activated in the host OS, which may require an HDR-capable display or EDID emulator dongle
      connected to your host PC.
    • You must also enable the HDR option in your Moonlight client settings, otherwise the stream will be SDR
      (and probably overexposed if your host is HDR).
    • A good HDR experience relies on proper HDR display calibration both in the OS and in game. HDR calibration can
      differ significantly between client and host displays.
    • You may also need to tune the brightness slider or HDR calibration options in game to the different HDR brightness
      capabilities of your client's display.
    • Some GPUs video encoders can produce lower image quality or encoding performance when streaming in HDR compared
      to SDR.

Additional information:

@tabs{
@tab{ Windows |

  • HDR streaming is supported for Intel, AMD, and NVIDIA GPUs that support encoding HEVC Main 10 or AV1 10-bit profiles.
  • We recommend calibrating the display by streaming the Windows HDR Calibration app to your client device and saving an HDR calibration profile to use while streaming.
  • Older games that use NVIDIA-specific NVAPI HDR rather than native Windows HDR support may not display properly in HDR.
    }

@tab{ Linux |

  • HDR streaming is supported for Intel and AMD GPUs that support encoding HEVC Main 10 or AV1 10-bit profiles using VAAPI.
  • The KMS capture backend is required for HDR capture. Other capture methods, like NvFBC or X11, do not support HDR.
  • You will need a desktop environment with a compositor that supports HDR rendering, such as Gamescope or KDE Plasma 6.

@seealso{Arch wiki on HDR Support for Linux and
Reddit Guide for HDR Support for AMD GPUs}
}
}

Tutorials and Guides

Tutorial videos are available here.

Guides are available here.

@admonition{Community! |
Tutorials and Guides are community generated. Want to contribute? Reach out to us on our discord server.}

Previous Next
Overview Changelog

[TOC]


File: docs/guides.md

Guides

@admonition{Community | A collection of guides written by the community is available on our
blog.
Feel free to contribute your own tips and trips by making a PR to
LizardByte.github.io.}

Previous Next
Awesome-Sunshine Performance Tuning

[TOC]

2. Official Technical Reference & Guides (LizardByte/LizardByte.github.io)

About

This repo contains the source files for the LizardByte website.

The page is built using jekyll and hosted on GitHub Pages.

CrowdIn Localization

Reusable Workflow

This repo contains a reusable workflow to allow for building gh-pages subprojects using the same configuration.

yml
---
name: Jekyll CI
permissions:
  contents: read

on:
 pull_request:
   branches:
     - master
   types:
     - opened
     - synchronize
     - reopened

concurrency:
 group: "${{ github.workflow }}-${{ github.ref }}"
 cancel-in-progress: true

jobs:
  prep:
    runs-on: ubuntu-latest
    steps:
      # Prepare your site here if needed, you can run any build steps needed to generate the site
      # The structure of the artifacts must be exactly as you expect to find the files in the final site
      # e.g. `index.html` should be at the root of the artifact, not in a subdirectory
      - name: Sample build
        run: echo "Hello, world!" > hello.txt

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: prep  # any name except 'site' is allowed
          path: hello.txt
          if-no-files-found: error
          include-hidden-files: true
          retention-days: 1

  call-jekyll-build:
    needs: prep
    uses: LizardByte/LizardByte.github.io/.github/workflows/jekyll-build.yml@master
    secrets:
      GH_BOT_EMAIL: ${{ secrets.GH_BOT_EMAIL }}
      GH_BOT_TOKEN: ${{ secrets.GH_BOT_TOKEN }}
    with:
      gh_bot_name: ${{ vars.GH_BOT_NAME }}
      site_artifact: 'prep'  # any name except 'site' is allowed
      target_branch: 'gh-pages'
      clean_gh_pages: true

For additional options see jekyll-build.yml

PR Previews

Changes to gh-pages can be previewed, by setting up the project in ReadTheDocs.
It is recommended to use the following manual configuration:

Initial setup:

yml
Name: LizardByte-gh-pages-<repo_name>  # the project slug cannot be changed after creation
Repository URL: https://github.com/LizardByte/<repo_name>.git
Default-branch: master
Language: English

Project Settings:

yml
Connected-repository: https://github.com/LizardByte/<repo_name>.git
URL-versioning-scheme: Multiple versions without translations
Path-for-.readthedocs.yaml:  # only set if not in the root of the repo
Programming-Language: Other
Project-homepage: https://app.lizardbyte.dev/<repo_name>
Build-pull-requests-for-this-project: true

Environment Variables:

yml
# REQUIRED
GITHUB_WORKFLOW: call-jekyll-build / Build Jekyll
SITE_ARTIFACT: prep.zip  # the name of the artifact to look for in the workflow

# OPTIONAL
CONFIG_FILE: _config.yml
EXTRACT_ARCHIVE: pre_built_database.zip  # if there is a nested archive to extract
GITHUB_TIMEOUT: 10  # timeout in minutes to use when searching for GitHub artifacts, max 15
THEME_REF: master

Additionally, do the following:

  1. Deactivate the stable version
  2. Make the latest version hidden
  3. Update branch protection rules in GitHub repo settings to require status checks from ReadTheDocs
  4. Add the below .readthedocs.yaml file to the root of the repo, or a custom path as specified in the project settings
yml
---
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

build:
  os: ubuntu-24.04
  tools:
    ruby: "3.3"
  apt_packages:
    - 7zip
    - jq
  jobs:
    install:
      - |
        mkdir -p "./tmp"
        branch="master"
        base_url="https://raw.githubusercontent.com/LizardByte/LizardByte.github.io"
        url="${base_url}/refs/heads/${branch}/scripts/readthedocs_build.sh"
        curl -sSL -o "./tmp/readthedocs_build.sh" "${url}"
        chmod +x "./tmp/readthedocs_build.sh"
    build:
      html:
        - "./tmp/readthedocs_build.sh"