From 7acabf446954d524ab437b50e4d8beda1b52c9ea Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Thu, 26 Feb 2026 09:39:45 +0000 Subject: [PATCH] fix(linux): use FQDN naming for all Linux packaging types Normalize install files to use the FQDN naming scheme for all package types (native/AppImage/Flatpak) to allow XDG compliance. * Use FQDN naming convention for icons. * Use "app-FQDN" naming convention for unprivileged systemd service; fixes XDG Desktop Portal app_id detection. * Restore privileged "sunshine-kms" service unit back to "sunshine" and restore as the default in documentation and via preset unit. The unprivileged service only needs XDG compliance. --- cmake/compile_definitions/linux.cmake | 7 +-- cmake/packaging/linux.cmake | 60 +++++++------------ cmake/prep/build_version.cmake | 2 + .../prep/special_package_configuration.cmake | 7 +-- docs/getting_started.md | 8 +-- docs/troubleshooting.md | 8 +-- ...-app-dev.lizardbyte.app.Sunshine.preset.in | 4 ++ packaging/linux/00-sunshine-kms.preset.in | 4 -- packaging/linux/AppImage/AppRun | 4 +- ...pp-dev.lizardbyte.app.Sunshine.service.in} | 3 +- packaging/linux/copr/Sunshine.spec | 9 ++- .../linux/dev.lizardbyte.app.Sunshine.desktop | 1 + .../flatpak/scripts/additional-install.sh | 4 +- .../scripts/remove-additional-install.sh | 4 +- packaging/linux/sunshine.service.in | 5 +- src/platform/linux/kmsgrab.cpp | 2 +- 16 files changed, 55 insertions(+), 77 deletions(-) create mode 100644 packaging/linux/00-app-dev.lizardbyte.app.Sunshine.preset.in delete mode 100644 packaging/linux/00-sunshine-kms.preset.in rename packaging/linux/{sunshine-kms.service.in => app-dev.lizardbyte.app.Sunshine.service.in} (76%) diff --git a/cmake/compile_definitions/linux.cmake b/cmake/compile_definitions/linux.cmake index 3758884fdce..a8e856ac848 100644 --- a/cmake/compile_definitions/linux.cmake +++ b/cmake/compile_definitions/linux.cmake @@ -217,12 +217,7 @@ if(${SUNSHINE_ENABLE_TRAY}) list(APPEND SUNSHINE_EXTERNAL_LIBRARIES ${APPINDICATOR_LIBRARIES} ${LIBNOTIFY_LIBRARIES}) endif() - # flatpak icons must be prefixed with the app id or they will not be included in the flatpak - if(${SUNSHINE_BUILD_FLATPAK}) - set(SUNSHINE_TRAY_PREFIX "${PROJECT_FQDN}") - else() - set(SUNSHINE_TRAY_PREFIX "sunshine") - endif() + set(SUNSHINE_TRAY_PREFIX "${PROJECT_FQDN}") list(APPEND SUNSHINE_DEFINITIONS SUNSHINE_TRAY_PREFIX="${SUNSHINE_TRAY_PREFIX}") else() set(SUNSHINE_TRAY 0) diff --git a/cmake/packaging/linux.cmake b/cmake/packaging/linux.cmake index d9538071f14..7b605d0660e 100644 --- a/cmake/packaging/linux.cmake +++ b/cmake/packaging/linux.cmake @@ -16,11 +16,11 @@ if(${SUNSHINE_BUILD_APPIMAGE} OR ${SUNSHINE_BUILD_FLATPAK}) DESTINATION "${SUNSHINE_ASSETS_DIR}/udev/rules.d") install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.conf" DESTINATION "${SUNSHINE_ASSETS_DIR}/modules-load.d") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/app-${PROJECT_FQDN}.service" DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine-kms.service" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-sunshine-kms.preset" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-app-${PROJECT_FQDN}.preset" DESTINATION "${SUNSHINE_ASSETS_DIR}/systemd/user-preset") else() find_package(Systemd) @@ -31,11 +31,11 @@ else() DESTINATION "${UDEV_RULES_INSTALL_DIR}") endif() if(SYSTEMD_FOUND) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/app-${PROJECT_FQDN}.service" DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine-kms.service" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sunshine.service" DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-sunshine-kms.preset" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/00-app-${PROJECT_FQDN}.preset" DESTINATION "${SYSTEMD_USER_PRESET_INSTALL_DIR}") install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.conf" DESTINATION "${SYSTEMD_MODULES_LOAD_DIR}") @@ -143,42 +143,24 @@ set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set(CPACK_RPM_PACKAGE_AUTOREQ ON) # application icon -if(NOT ${SUNSHINE_BUILD_FLATPAK}) - install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps") -else() - install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps" - RENAME "${PROJECT_FQDN}.svg") -endif() +install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps" + RENAME "${PROJECT_FQDN}.svg") # tray icon if(${SUNSHINE_TRAY} STREQUAL 1) - if(NOT ${SUNSHINE_BUILD_FLATPAK}) - install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" - RENAME "sunshine-tray.svg") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-playing.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-pausing.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-locked.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status") - else() - # flatpak icons must be prefixed with the app id or they will not be included in the flatpak - install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" - RENAME "${PROJECT_FQDN}-tray.svg") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-playing.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" - RENAME "${PROJECT_FQDN}-playing.svg") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-pausing.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" - RENAME "${PROJECT_FQDN}-pausing.svg") - install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-locked.svg" - DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" - RENAME "${PROJECT_FQDN}-locked.svg") - endif() + install(FILES "${CMAKE_SOURCE_DIR}/sunshine.svg" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" + RENAME "${PROJECT_FQDN}-tray.svg") + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-playing.svg" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" + RENAME "${PROJECT_FQDN}-playing.svg") + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-pausing.svg" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" + RENAME "${PROJECT_FQDN}-pausing.svg") + install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/common/assets/web/public/images/sunshine-locked.svg" + DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status" + RENAME "${PROJECT_FQDN}-locked.svg") set(CPACK_DEBIAN_PACKAGE_DEPENDS "\ ${CPACK_DEBIAN_PACKAGE_DEPENDS}, \ diff --git a/cmake/prep/build_version.cmake b/cmake/prep/build_version.cmake index 91209922066..4508a91ad98 100644 --- a/cmake/prep/build_version.cmake +++ b/cmake/prep/build_version.cmake @@ -127,6 +127,7 @@ endif() math(EXPR RC_VERSION_BUILD "${PROJECT_VERSION_PATCH} / 100") math(EXPR RC_VERSION_REVISION "${PROJECT_VERSION_PATCH} % 100") +message("PROJECT_FQDN: ${PROJECT_FQDN}") message("PROJECT_NAME: ${PROJECT_NAME}") message("PROJECT_VERSION: ${PROJECT_VERSION}") message("PROJECT_VERSION_MAJOR: ${PROJECT_VERSION_MAJOR}") @@ -142,6 +143,7 @@ message("PROJECT_YEAR: ${PROJECT_YEAR}") message("PROJECT_MONTH: ${PROJECT_MONTH}") message("PROJECT_DAY: ${PROJECT_DAY}") +list(APPEND SUNSHINE_DEFINITIONS PROJECT_FQDN="${PROJECT_FQDN}") list(APPEND SUNSHINE_DEFINITIONS PROJECT_NAME="${PROJECT_NAME}") list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION="${PROJECT_VERSION}") list(APPEND SUNSHINE_DEFINITIONS PROJECT_VERSION_MAJOR="${PROJECT_VERSION_MAJOR}") diff --git a/cmake/prep/special_package_configuration.cmake b/cmake/prep/special_package_configuration.cmake index f7e51d31e4b..a038cef25e5 100644 --- a/cmake/prep/special_package_configuration.cmake +++ b/cmake/prep/special_package_configuration.cmake @@ -10,11 +10,10 @@ if(APPLE) endif() elseif(UNIX) # configure the .desktop file - set(SUNSHINE_DESKTOP_ICON "sunshine") + set(SUNSHINE_DESKTOP_ICON "${PROJECT_FQDN}") if(${SUNSHINE_BUILD_APPIMAGE}) configure_file(packaging/linux/AppImage/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY) elseif(${SUNSHINE_BUILD_FLATPAK}) - set(SUNSHINE_DESKTOP_ICON "${PROJECT_FQDN}") configure_file(packaging/linux/flatpak/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY) else() configure_file(packaging/linux/${PROJECT_FQDN}.desktop ${PROJECT_FQDN}.desktop @ONLY) @@ -25,9 +24,9 @@ elseif(UNIX) configure_file(packaging/linux/${PROJECT_FQDN}.metainfo.xml ${PROJECT_FQDN}.metainfo.xml @ONLY) # configure service + configure_file(packaging/linux/app-${PROJECT_FQDN}.service.in app-${PROJECT_FQDN}.service @ONLY) configure_file(packaging/linux/sunshine.service.in sunshine.service @ONLY) - configure_file(packaging/linux/sunshine-kms.service.in sunshine-kms.service @ONLY) - configure_file(packaging/linux/00-sunshine-kms.preset.in 00-sunshine-kms.preset @ONLY) + configure_file(packaging/linux/00-app-${PROJECT_FQDN}.preset.in 00-app-${PROJECT_FQDN}.preset @ONLY) # configure the arch linux pkgbuild if(${SUNSHINE_CONFIGURE_PKGBUILD}) diff --git a/docs/getting_started.md b/docs/getting_started.md index 5daccc041c2..a8c83c35e3b 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -429,17 +429,17 @@ After adding yourself to the group, log out and log back in for the changes to t #### Services > [!NOTE] -> Two service unit files are available. Pick "sunshine" for unprivileged XDG Portal or X11 capture, otherwise -> pick "sunshine-kms" for privileged KMS capture. +> Two service unit files are available. Pick "app-dev.lizardbyte.app.Sunshine" for unprivileged XDG Portal +> or X11 capture, otherwise pick "sunshine" for privileged KMS capture. **Start once** ```bash systemctl --user start sunshine ``` -**Start on boot (unprivileged; swap logic for KMS)** +**Start on boot (privileged; swap names for unprivileged XDG capture)** ```bash -systemctl --user --now disable sunshine-kms +systemctl --user --now disable app-dev.lizardbyte.app.Sunshine systemctl --user --now enable sunshine ``` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 61c1ec594b3..6be4bb6c01c 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -160,12 +160,12 @@ sudo usermod -aG input $USER ``` ### KMS Streaming fails -If screencasting fails with KMS, you may be using the unprivileged sunshine service unit. Switch to the privileged -sunshine-kms service: +If screencasting fails with KMS, you may be using the unprivileged app-dev.lizardbyte.app.Sunshine service unit. +Switch to the privileged sunshine service: ```bash -systemctl --user --now disable sunshine -systemctl --user --now enable sunshine-kms +systemctl --user --now disable app-dev.lizardbyte.app.Sunshine +systemctl --user --now enable sunshine ``` > [!NOTE] diff --git a/packaging/linux/00-app-dev.lizardbyte.app.Sunshine.preset.in b/packaging/linux/00-app-dev.lizardbyte.app.Sunshine.preset.in new file mode 100644 index 00000000000..cd8394752d5 --- /dev/null +++ b/packaging/linux/00-app-dev.lizardbyte.app.Sunshine.preset.in @@ -0,0 +1,4 @@ +# @PROJECT_DESCRIPTION@ +# The unprivileged service should preset to disabled + +disable app-@PROJECT_FQDN@.service diff --git a/packaging/linux/00-sunshine-kms.preset.in b/packaging/linux/00-sunshine-kms.preset.in deleted file mode 100644 index 5019b8292e9..00000000000 --- a/packaging/linux/00-sunshine-kms.preset.in +++ /dev/null @@ -1,4 +0,0 @@ -# @PROJECT_DESCRIPTION@ -# KMS service should preset to disabled - -disable sunshine-kms.service diff --git a/packaging/linux/AppImage/AppRun b/packaging/linux/AppImage/AppRun index c021e425936..da2ff631cce 100644 --- a/packaging/linux/AppImage/AppRun +++ b/packaging/linux/AppImage/AppRun @@ -57,7 +57,7 @@ function install() { mkdir -p ~/.config/systemd/user cp -r "$SUNSHINE_SHARE_HERE/systemd/user/" ~/.config/systemd/ # patch service executable path - sed -i -e "s#$SUNSHINE_PATH#$(readlink -f $ARGV0)#g" ~/.config/systemd/user/sunshine.service + sed -i -e "s#$SUNSHINE_PATH#$(readlink -f $ARGV0)#g" ~/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service # setcap sudo setcap cap_sys_admin+p "$(readlink -f "$SUNSHINE_BIN_HERE")" @@ -71,7 +71,7 @@ function remove() { sudo rm -f /etc/modules-load.d/60-sunshine.conf # remove service - sudo rm -f ~/.config/systemd/user/sunshine.service + sudo rm -f ~/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service } # process arguments diff --git a/packaging/linux/sunshine-kms.service.in b/packaging/linux/app-dev.lizardbyte.app.Sunshine.service.in similarity index 76% rename from packaging/linux/sunshine-kms.service.in rename to packaging/linux/app-dev.lizardbyte.app.Sunshine.service.in index 80defd58d57..7ae9487e558 100644 --- a/packaging/linux/sunshine-kms.service.in +++ b/packaging/linux/app-dev.lizardbyte.app.Sunshine.service.in @@ -3,7 +3,7 @@ Description=@PROJECT_DESCRIPTION@ StartLimitIntervalSec=500 StartLimitBurst=5 Conflicts=sunshine.service -After=graphical-session.target xdg-desktop-autostart.target +After=graphical-session.target xdg-desktop-autostart.target xdg-desktop-portal.service [Service] # Avoid starting Sunshine before the desktop is fully initialized. @@ -12,6 +12,7 @@ ExecStartPre=/bin/sleep 5 @SUNSHINE_SERVICE_STOP_COMMAND@ Restart=on-failure RestartSec=5s +NoNewPrivileges=true [Install] WantedBy=graphical-session.target diff --git a/packaging/linux/copr/Sunshine.spec b/packaging/linux/copr/Sunshine.spec index 572f518350c..1b2615a2179 100644 --- a/packaging/linux/copr/Sunshine.spec +++ b/packaging/linux/copr/Sunshine.spec @@ -369,9 +369,8 @@ fi %caps(cap_sys_admin+p) %{_bindir}/sunshine-* # Systemd unit/preset files for user services -%{_userunitdir}/sunshine.service -%{_userunitdir}/sunshine-kms.service -%{_userpresetdir}/00-sunshine-kms.preset +%{_userunitdir}/*.service +%{_userpresetdir}/*.preset # Udev rules %{_udevrulesdir}/*-sunshine.rules @@ -383,8 +382,8 @@ fi %{_datadir}/applications/*.desktop # Icons -%{_datadir}/icons/hicolor/scalable/apps/sunshine.svg -%{_datadir}/icons/hicolor/scalable/status/sunshine*.svg +%{_datadir}/icons/hicolor/scalable/apps/*.Sunshine.svg +%{_datadir}/icons/hicolor/scalable/status/*.Sunshine-*.svg # Metainfo %{_datadir}/metainfo/*.metainfo.xml diff --git a/packaging/linux/dev.lizardbyte.app.Sunshine.desktop b/packaging/linux/dev.lizardbyte.app.Sunshine.desktop index 29252ae53e1..9f66261bbc1 100644 --- a/packaging/linux/dev.lizardbyte.app.Sunshine.desktop +++ b/packaging/linux/dev.lizardbyte.app.Sunshine.desktop @@ -4,6 +4,7 @@ Categories=RemoteAccess;Network; Comment=@PROJECT_DESCRIPTION@ Exec=/usr/bin/env systemctl start --u sunshine Icon=@SUNSHINE_DESKTOP_ICON@ +StartupWMClass=@PROJECT_FQDN@ Keywords=gamestream;stream;moonlight;remote play; Name=@PROJECT_NAME@ Type=Application diff --git a/packaging/linux/flatpak/scripts/additional-install.sh b/packaging/linux/flatpak/scripts/additional-install.sh index 5cd6cfbc809..4b65c0988eb 100644 --- a/packaging/linux/flatpak/scripts/additional-install.sh +++ b/packaging/linux/flatpak/scripts/additional-install.sh @@ -2,9 +2,9 @@ # User Service mkdir -p ~/.config/systemd/user -cp "/app/share/sunshine/systemd/user/sunshine.service" "$HOME/.config/systemd/user/sunshine.service" +cp "/app/share/sunshine/systemd/user/app-dev.lizardbyte.app.Sunshine.service" "$HOME/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service" echo "Sunshine User Service has been installed." -echo "Use [systemctl --user enable sunshine] once to autostart Sunshine on login." +echo "Use [systemctl --user enable app-dev.lizardbyte.app.Sunshine] once to autostart Sunshine on login." # Load uhid (DS5 emulation) UHID=$(cat /app/share/sunshine/modules-load.d/60-sunshine.conf) diff --git a/packaging/linux/flatpak/scripts/remove-additional-install.sh b/packaging/linux/flatpak/scripts/remove-additional-install.sh index b3b30149bc6..920ce761f82 100644 --- a/packaging/linux/flatpak/scripts/remove-additional-install.sh +++ b/packaging/linux/flatpak/scripts/remove-additional-install.sh @@ -1,8 +1,8 @@ #!/bin/sh # User Service -systemctl --user stop sunshine -rm "$HOME/.config/systemd/user/sunshine.service" +systemctl --user stop app-dev.lizardbyte.app.Sunshine +rm "$HOME/.config/systemd/user/app-dev.lizardbyte.app.Sunshine.service" systemctl --user daemon-reload echo "Sunshine User Service has been removed." diff --git a/packaging/linux/sunshine.service.in b/packaging/linux/sunshine.service.in index 33dd8caa927..ea8feb314bd 100644 --- a/packaging/linux/sunshine.service.in +++ b/packaging/linux/sunshine.service.in @@ -2,8 +2,8 @@ Description=@PROJECT_DESCRIPTION@ StartLimitIntervalSec=500 StartLimitBurst=5 -Conflicts=sunshine-kms.service -After=graphical-session.target xdg-desktop-autostart.target xdg-desktop-portal.service +Conflicts=app-@PROJECT_FQDN@.service +After=graphical-session.target xdg-desktop-autostart.target [Service] # Avoid starting Sunshine before the desktop is fully initialized. @@ -12,7 +12,6 @@ ExecStartPre=/bin/sleep 5 @SUNSHINE_SERVICE_STOP_COMMAND@ Restart=on-failure RestartSec=5s -NoNewPrivileges=true [Install] WantedBy=graphical-session.target diff --git a/src/platform/linux/kmsgrab.cpp b/src/platform/linux/kmsgrab.cpp index 7859bcd3bb1..83fc664361f 100644 --- a/src/platform/linux/kmsgrab.cpp +++ b/src/platform/linux/kmsgrab.cpp @@ -1676,7 +1676,7 @@ namespace platf { #if defined(SUNSHINE_BUILD_FLATPAK) || defined(SUNSHINE_BUILD_APPIMAGE) << "AppImage and Flatpak do not support KMS capture. Use another capture method."sv; #else - << "You must use the 'sunshine-kms' service instead of the 'sunshine' service for KMS capture.\n"sv + << "You must use the 'sunshine' service instead of the 'app-" << PROJECT_FQDN << "' service for KMS capture.\n"sv << "Please refer to the official documentation:\n"sv << " stable: https://docs.lizardbyte.dev/projects/sunshine/latest/md_docs_2getting__started.html#linux-1"sv << " beta: https://docs.lizardbyte.dev/projects/sunshine/master/md_docs_2getting__started.html#linux-1"sv;