diff --git a/docker/ubuntu-26.04.dockerfile b/docker/ubuntu-26.04.dockerfile
new file mode 100644
index 000000000..33ff5a25e
--- /dev/null
+++ b/docker/ubuntu-26.04.dockerfile
@@ -0,0 +1,133 @@
+# syntax=docker/dockerfile:1
+# artifacts: true
+# platforms: linux/amd64,linux/arm64/v8
+# platforms_pr: linux/amd64
+# no-cache-filters: sunshine-base,artifacts,sunshine
+ARG BASE=ubuntu
+ARG TAG=26.04
+FROM ${BASE}:${TAG} AS sunshine-base
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+FROM sunshine-base AS sunshine-deps
+
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+# Copy only the build script first for better layer caching
+WORKDIR /build/sunshine/
+COPY --link scripts/linux_build.sh ./scripts/linux_build.sh
+
+# Install dependencies first - this layer will be cached
+RUN <<_DEPS
+#!/bin/bash
+set -e
+chmod +x ./scripts/linux_build.sh
+./scripts/linux_build.sh \
+ --step=deps \
+ --sudo-off
+apt-get clean
+rm -rf /var/lib/apt/lists/*
+_DEPS
+
+FROM sunshine-deps AS sunshine-build
+
+ARG BRANCH
+ARG BUILD_VERSION
+ARG COMMIT
+# note: BUILD_VERSION may be blank
+
+ENV BRANCH=${BRANCH}
+ENV BUILD_VERSION=${BUILD_VERSION}
+ENV COMMIT=${COMMIT}
+
+# Now copy the full repository
+COPY --link .. .
+
+# Configure, validate, build and package
+RUN <<_BUILD
+#!/bin/bash
+set -e
+./scripts/linux_build.sh \
+ --step=cmake \
+ --publisher-name='LizardByte' \
+ --publisher-website='https://app.lizardbyte.dev' \
+ --publisher-issue-url='https://app.lizardbyte.dev/support' \
+ --sudo-off
+
+./scripts/linux_build.sh \
+ --step=validation \
+ --sudo-off
+
+./scripts/linux_build.sh \
+ --step=build \
+ --sudo-off
+
+./scripts/linux_build.sh \
+ --step=package \
+ --sudo-off
+_BUILD
+
+# run tests
+WORKDIR /build/sunshine/build/tests
+RUN <<_TEST
+#!/bin/bash
+set -e
+export DISPLAY=:1
+Xvfb ${DISPLAY} -screen 0 1024x768x24 &
+./test_sunshine --gtest_color=yes
+_TEST
+
+FROM sunshine-base AS sunshine
+
+ARG BASE
+ARG TAG
+ARG TARGETARCH
+
+# artifacts to be extracted in CI
+COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /artifacts/sunshine-${BASE}-${TAG}-${TARGETARCH}.deb
+
+# copy deb from builder
+COPY --link --from=sunshine-build /build/sunshine/build/cpack_artifacts/Sunshine.deb /sunshine.deb
+
+# install sunshine
+RUN <<_INSTALL_SUNSHINE
+#!/bin/bash
+set -e
+apt-get update -y
+apt-get install -y --no-install-recommends /sunshine.deb
+apt-get clean
+rm -rf /var/lib/apt/lists/*
+_INSTALL_SUNSHINE
+
+# network setup
+EXPOSE 47984-47990/tcp
+EXPOSE 48010
+EXPOSE 47998-48000/udp
+
+# setup user
+ARG PGID=1001
+ENV PGID=${PGID}
+ARG PUID=1001
+ENV PUID=${PUID}
+ENV TZ="UTC"
+ARG UNAME=lizard
+ENV UNAME=${UNAME}
+
+ENV HOME=/home/$UNAME
+
+# setup user
+RUN <<_SETUP_USER
+#!/bin/bash
+set -e
+groupadd -f -g "${PGID}" "${UNAME}"
+useradd -lm -d ${HOME} -s /bin/bash -g "${PGID}" -u "${PUID}" "${UNAME}"
+mkdir -p ${HOME}/.config/sunshine
+ln -s ${HOME}/.config/sunshine /config
+chown -R ${UNAME} ${HOME}
+_SETUP_USER
+
+USER ${UNAME}
+WORKDIR ${HOME}
+
+# entrypoint
+ENTRYPOINT ["/usr/bin/sunshine"]
diff --git a/docs/building.md b/docs/building.md
index 91c0dd3d5..54d195b7f 100644
--- a/docs/building.md
+++ b/docs/building.md
@@ -69,7 +69,7 @@ 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 ~12.9.
+ At the time of writing, the recommended version to use is CUDA ~13.1.
See [CUDA compatibility](https://docs.nvidia.com/deploy/cuda-compatibility/index.html) for more info.
> [!NOTE]
diff --git a/docs/getting_started.md b/docs/getting_started.md
index dc7b8e4a4..c82117480 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -68,8 +68,8 @@ CUDA is used for NVFBC capture.
Package |
- | 12.9.1 |
- 575.57.08 |
+ 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 |
diff --git a/scripts/linux_build.sh b/scripts/linux_build.sh
index f4a6d2bfe..00fc97dee 100755
--- a/scripts/linux_build.sh
+++ b/scripts/linux_build.sh
@@ -7,10 +7,17 @@ target_cmake_version="3.30.1"
doxygen_min="1.10.0"
_doxygen_min="${doxygen_min//\./_}" # Convert dots to underscores for URL
doxygen_max="1.12.0"
+default_cuda_version="13.1.1"
+default_cuda_build="590.48.01"
# Default value for arguments
appimage_build=0
+cuda_version="$default_cuda_version"
+cuda_build="$default_cuda_build"
cuda_patches=0
+cuda_system_package=0
+cuda_system_package_name=""
+force_cuda_runfile=0
num_processors=$(nproc)
publisher_name="Third Party Publisher"
publisher_website=""
@@ -27,6 +34,97 @@ step="all"
AARCH64="aarch64"
DOXYGEN="doxygen"
+function setup_cuda_system_package_environment() {
+ if [[ "$cuda_system_package" == 1 ]]; then
+ # Ubuntu CUDA 13 packages install nvcc here but do not add it to PATH.
+ local cuda_bin_path
+ cuda_bin_path="$(cuda_system_toolkit_path)/bin"
+ if [[ ":${PATH}:" != *":${cuda_bin_path}:"* ]]; then
+ export PATH="${cuda_bin_path}:${PATH}"
+ fi
+ fi
+ return 0
+}
+
+function cuda_system_toolkit_path() {
+ local cuda_minor_version="${cuda_version%.*}"
+ echo "/usr/local/cuda-${cuda_minor_version}"
+}
+
+function cuda_target_dir() {
+ if [[ "$architecture" == "${AARCH64}" ]]; then
+ echo "sbsa-linux"
+ else
+ echo "x86_64-linux"
+ fi
+}
+
+function cuda_math_functions_patch_applied() {
+ local cuda_toolkit_path=$1
+ local math_functions_file
+ math_functions_file="${cuda_toolkit_path}/targets/$(cuda_target_dir)/include/crt/math_functions.h"
+
+ if [[ ! -f "$math_functions_file" ]]; then
+ return 1
+ fi
+
+ grep -Fq "rsqrt(double x) noexcept (true)" "$math_functions_file" && \
+ grep -Fq "rsqrtf(float x) noexcept (true)" "$math_functions_file" && \
+ grep -Fq "__func__(double rsqrt(double a) noexcept (true));" "$math_functions_file" && \
+ grep -Fq "__func__(float rsqrtf(float a) noexcept (true));" "$math_functions_file"
+}
+
+function apply_cuda_patches() {
+ local cuda_toolkit_path=$1
+
+ if [[ "$cuda_patches" != 1 ]]; then
+ return 0
+ fi
+
+ if [[ ! -d "$cuda_toolkit_path" ]]; then
+ echo "CUDA toolkit path not found: $cuda_toolkit_path"
+ return 1
+ fi
+
+ if cuda_math_functions_patch_applied "$cuda_toolkit_path"; then
+ echo "CUDA math_functions.h patch already applied"
+ return 0
+ fi
+
+ echo "Applying CUDA patches"
+ local patch_dir="${script_dir}/../packaging/linux/patches/${architecture}"
+ local patch_file=""
+
+ # Select the patch based on the CUDA major version, not the distro version.
+ # see https://forums.developer.nvidia.com/t/error-exception-specification-is-incompatible-for-cospi-sinpi-cospif-sinpif-with-glibc-2-41/323591/3
+ local cuda_major="${cuda_version%%.*}"
+ if [[ "${cuda_major}" -eq 12 ]]; then
+ # CUDA 12.x: the extern declarations lack noexcept(true); add it to match glibc 2.41.
+ patch_file="${patch_dir}/cuda-12-math_functions.patch"
+ elif [[ "${cuda_major}" -eq 13 ]]; then
+ # CUDA 13.x: the extern declarations already have noexcept(true), but the __func__()
+ # macro invocations at the bottom still lack it, causing a redeclaration conflict.
+ patch_file="${patch_dir}/cuda-13-math_functions.patch"
+ else
+ echo "Warning: no math_functions.h patch available for CUDA ${cuda_major}.x, skipping."
+ fi
+
+ if [[ -n "$patch_file" ]]; then
+ if [[ -f "$patch_file" ]]; then
+ echo "Applying patch: $patch_file"
+ ${sudo_cmd} patch -p2 \
+ --backup \
+ --directory="$cuda_toolkit_path" \
+ --verbose \
+ < "$patch_file"
+ else
+ echo "Patch file not found: $patch_file"
+ fi
+ else
+ echo "No CUDA patch required for ${distro} ${version}"
+ fi
+}
+
# Reusable function to detect nvcc path
function detect_nvcc_path() {
local nvcc_path=""
@@ -81,7 +179,10 @@ Options:
-h, --help Display this help message.
-s, --sudo-off Disable sudo command.
--appimage-build Compile for AppImage, this will not create the AppImage, just the executable.
- --cuda-patches Apply cuda patches.
+ --cuda-patches Apply cuda patches. Enabled automatically on Ubuntu 26.04.
+ --cuda-runfile Force CUDA installation from the NVIDIA runfile.
+ --cuda-system-package=* The CUDA package to install when system CUDA is enabled.
+ Default for Ubuntu 26.04 is cuda-toolkit-13-1.
--num-processors The number of processors to use for compilation. Default is the value of 'nproc'.
--publisher-name The name of the publisher (not developer) of the application.
--publisher-website The URL of the publisher's website.
@@ -122,6 +223,12 @@ while getopts ":hs-:" opt; do
cuda-patches)
cuda_patches=1
;;
+ cuda-runfile)
+ force_cuda_runfile=1
+ ;;
+ cuda-system-package=*)
+ cuda_system_package_name="${OPTARG#*=}"
+ ;;
num-processors=*)
num_processors="${OPTARG#*=}"
;;
@@ -229,6 +336,7 @@ function add_debian_based_deps() {
"g++-${gcc_version}"
"git"
"graphviz"
+ "libayatana-appindicator3-dev"
"libcap-dev" # KMS
"libcurl4-openssl-dev"
"libdrm-dev" # KMS
@@ -283,7 +391,6 @@ function add_debian_deps() {
add_test_ppa
add_debian_based_deps
dependencies+=(
- "libayatana-appindicator3-dev"
"systemd-dev"
)
return 0
@@ -292,9 +399,24 @@ function add_debian_deps() {
function add_ubuntu_deps() {
add_test_ppa
add_debian_based_deps
- dependencies+=(
- "libappindicator3-dev"
- )
+
+ if [[ "$skip_cuda" == 0 ]] && [[ "$cuda_system_package" == 1 ]]; then
+ if [[ -z "$cuda_system_package_name" ]]; then
+ echo "CUDA system package was requested, but no package name was configured."
+ return 1
+ fi
+
+ echo "Using CUDA system package: $cuda_system_package_name"
+ dependencies+=(
+ "$cuda_system_package_name"
+ )
+ fi
+
+ if [[ "$(printf '%s\n' "$version" "24.04" | sort -V | head -n1)" == "24.04" ]]; then
+ dependencies+=(
+ "systemd-dev"
+ )
+ fi
return 0
}
@@ -352,9 +474,22 @@ function add_fedora_deps() {
}
function install_cuda() {
+ setup_cuda_system_package_environment
+
# Check if CUDA is already available
- if detect_nvcc_path > /dev/null 2>&1; then
+ if [[ "$force_cuda_runfile" == 1 ]] && [[ -f "${build_dir}/cuda/bin/nvcc" ]]; then
+ apply_cuda_patches "${build_dir}/cuda"
return
+ elif [[ "$force_cuda_runfile" == 0 ]] && detect_nvcc_path > /dev/null 2>&1; then
+ if [[ "$cuda_system_package" == 1 ]]; then
+ apply_cuda_patches "$(cuda_system_toolkit_path)"
+ fi
+ return
+ fi
+
+ if [[ "$cuda_system_package" == 1 ]]; then
+ echo "CUDA system package '$cuda_system_package_name' was requested, but nvcc was not found after dependency installation."
+ return 1
fi
local cuda_override_arg=""
@@ -396,41 +531,7 @@ function install_cuda() {
"${build_dir}/cuda.run" --silent --toolkit --toolkitpath="${build_dir}/cuda" --no-opengl-libs --no-man-page --no-drm "$cuda_override_arg"
rm "${build_dir}/cuda.run"
- # run cuda patches
- if [[ "$cuda_patches" == 1 ]]; then
- echo "Applying CUDA patches"
- local patch_dir="${script_dir}/../packaging/linux/patches/${architecture}"
- local patch_file=""
-
- # Select the patch based on the CUDA major version, not the distro version.
- # see https://forums.developer.nvidia.com/t/error-exception-specification-is-incompatible-for-cospi-sinpi-cospif-sinpif-with-glibc-2-41/323591/3
- local cuda_major="${cuda_version%%.*}"
- if [[ "${cuda_major}" -eq 12 ]]; then
- # CUDA 12.x: the extern declarations lack noexcept(true); add it to match glibc 2.41.
- patch_file="${patch_dir}/cuda-12-math_functions.patch"
- elif [[ "${cuda_major}" -eq 13 ]]; then
- # CUDA 13.x: the extern declarations already have noexcept(true), but the __func__()
- # macro invocations at the bottom still lack it, causing a redeclaration conflict.
- patch_file="${patch_dir}/cuda-13-math_functions.patch"
- else
- echo "Warning: no math_functions.h patch available for CUDA ${cuda_major}.x, skipping."
- fi
-
- if [[ -n "$patch_file" ]]; then
- if [[ -f "$patch_file" ]]; then
- echo "Applying patch: $patch_file"
- patch -p2 \
- --backup \
- --directory="${build_dir}/cuda" \
- --verbose \
- < "$patch_file"
- else
- echo "Patch file not found: $patch_file"
- fi
- else
- echo "No CUDA patch required for ${distro} ${version}"
- fi
- fi
+ apply_cuda_patches "${build_dir}/cuda"
return 0
}
@@ -556,11 +657,19 @@ function run_step_cmake() {
# Setup NVM environment if needed (for web UI builds)
setup_nvm_environment
+ setup_cuda_system_package_environment
+ if [[ "$skip_cuda" == 0 ]] && [[ "$cuda_system_package" == 1 ]]; then
+ apply_cuda_patches "$(cuda_system_toolkit_path)"
+ fi
# Detect CUDA path using the reusable function
nvcc_path=""
if [[ "$skip_cuda" == 0 ]]; then
- nvcc_path=$(detect_nvcc_path)
+ if [[ "$force_cuda_runfile" == 1 ]] && [[ -f "${build_dir}/cuda/bin/nvcc" ]]; then
+ nvcc_path="${build_dir}/cuda/bin/nvcc"
+ else
+ nvcc_path=$(detect_nvcc_path)
+ fi
fi
#set gcc version based on distros
@@ -723,8 +832,6 @@ elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
version="12"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="13"
nvm_node=0
elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
@@ -732,8 +839,6 @@ elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
version="13"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=0
elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then
@@ -741,8 +846,6 @@ elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then
version="42"
package_update_command="${sudo_cmd} dnf update -y"
package_install_command="${sudo_cmd} dnf install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=0
elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=43$' /etc/os-release; then
@@ -750,8 +853,6 @@ elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=43$' /etc/os-
version="43"
package_update_command="${sudo_cmd} dnf update -y"
package_install_command="${sudo_cmd} dnf install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=0
elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=44$' /etc/os-release; then
@@ -759,8 +860,6 @@ elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=44$' /etc/os-
version="44"
package_update_command="${sudo_cmd} dnf update -y"
package_install_command="${sudo_cmd} dnf install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=0
elif grep -q '^ID=fedora$' /etc/os-release && grep -q '^VERSION_ID=45$' /etc/os-release; then
@@ -777,8 +876,6 @@ elif grep -q "Ubuntu 22.04" /etc/os-release; then
version="22.04"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=1
elif grep -q "Ubuntu 24.04" /etc/os-release; then
@@ -786,8 +883,6 @@ elif grep -q "Ubuntu 24.04" /etc/os-release; then
version="24.04"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=1
elif grep -q "Ubuntu 25.04" /etc/os-release; then
@@ -795,8 +890,6 @@ elif grep -q "Ubuntu 25.04" /etc/os-release; then
version="25.04"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
gcc_version="14"
nvm_node=0
elif grep -q "Ubuntu 25.10" /etc/os-release; then
@@ -804,8 +897,20 @@ elif grep -q "Ubuntu 25.10" /etc/os-release; then
version="25.10"
package_update_command="${sudo_cmd} apt-get update"
package_install_command="${sudo_cmd} apt-get install -y"
- cuda_version="12.9.1"
- cuda_build="575.57.08"
+ gcc_version="14"
+ nvm_node=0
+elif grep -q 'VERSION_ID="26.04"' /etc/os-release; then
+ distro="ubuntu"
+ version="26.04"
+ package_update_command="${sudo_cmd} apt-get update"
+ package_install_command="${sudo_cmd} apt-get install -y"
+ cuda_patches=1
+ if [[ "$force_cuda_runfile" == 0 ]]; then
+ cuda_system_package=1
+ if [[ -z "$cuda_system_package_name" ]]; then
+ cuda_system_package_name="cuda-toolkit-13-1"
+ fi
+ fi
gcc_version="14"
nvm_node=0
else