desktop-entrypoint.sh 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #!/bin/bash
  2. set -Eeuo pipefail
  3. export DISPLAY="${DISPLAY:-:20}"
  4. export DISPLAY_SIZEW="${DISPLAY_SIZEW:-1920}"
  5. export DISPLAY_SIZEH="${DISPLAY_SIZEH:-1080}"
  6. export DISPLAY_REFRESH="${DISPLAY_REFRESH:-120}"
  7. export DISPLAY_DPI="${DISPLAY_DPI:-96}"
  8. export DISPLAY_CDEPTH="${DISPLAY_CDEPTH:-24}"
  9. export VIDEO_PORT="${VIDEO_PORT:-HDMI-0}"
  10. export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp/runtime-ubuntu}"
  11. export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-${XDG_RUNTIME_DIR}}"
  12. export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR}/pulse}"
  13. export PULSE_SERVER="${PULSE_SERVER:-unix:${PULSE_RUNTIME_PATH}/native}"
  14. XORG_PID=""
  15. XFCE_PID=""
  16. cleanup() {
  17. echo "[desktop] Stopping XFCE/Xorg..."
  18. if [[ -n "${XFCE_PID}" ]] && kill -0 "${XFCE_PID}" 2>/dev/null; then
  19. kill -TERM "${XFCE_PID}" 2>/dev/null || true
  20. fi
  21. if [[ -n "${XORG_PID}" ]] && kill -0 "${XORG_PID}" 2>/dev/null; then
  22. kill -TERM "${XORG_PID}" 2>/dev/null || true
  23. fi
  24. }
  25. trap cleanup EXIT HUP INT QUIT TERM
  26. echo "[desktop] Preparing X11 runtime..."
  27. sudo install -d -m 1777 /tmp/.X11-unix /tmp/.ICE-unix
  28. sudo rm -f "/tmp/.X${DISPLAY#:}-lock"
  29. # Do not wipe the whole user cache: Steam may use it.
  30. rm -rf "${HOME}/.cache/sessions" 2>/dev/null || true
  31. if ! command -v nvidia-smi >/dev/null 2>&1; then
  32. echo "[desktop] ERROR: nvidia-smi is not available." >&2
  33. exit 1
  34. fi
  35. if ! command -v nvidia-xconfig >/dev/null 2>&1; then
  36. echo "[desktop] ERROR: nvidia-xconfig is not available." >&2
  37. exit 1
  38. fi
  39. GPU_SELECT="$(
  40. nvidia-smi --query-gpu=uuid --format=csv,noheader | head -n 1 | tr -d '[:space:]'
  41. )"
  42. if [[ -z "${GPU_SELECT}" ]]; then
  43. echo "[desktop] ERROR: no visible NVIDIA GPU detected." >&2
  44. exit 1
  45. fi
  46. HEX_ID="$(
  47. nvidia-smi --id="${GPU_SELECT}" --query-gpu=pci.bus_id --format=csv,noheader | head -n 1 | tr -d '[:space:]'
  48. )"
  49. if [[ -z "${HEX_ID}" ]]; then
  50. echo "[desktop] ERROR: unable to determine NVIDIA PCI bus ID." >&2
  51. exit 1
  52. fi
  53. IFS=':.' read -r DOMAIN BUS DEVICE FUNCTION <<<"${HEX_ID}"
  54. BUS_ID="PCI:$((16#${BUS}))@$((16#${DOMAIN})):$((16#${DEVICE})):$((16#${FUNCTION}))"
  55. echo "[desktop] GPU UUID : ${GPU_SELECT}"
  56. echo "[desktop] GPU PCI : ${HEX_ID} -> ${BUS_ID}"
  57. MODELINE="$(
  58. cvt -r "${DISPLAY_SIZEW}" "${DISPLAY_SIZEH}" "${DISPLAY_REFRESH}" | sed -n '2p'
  59. )"
  60. if [[ -z "${MODELINE}" ]]; then
  61. echo "[desktop] ERROR: cvt failed to generate a modeline." >&2
  62. exit 1
  63. fi
  64. MODE_NAME="$(
  65. awk '{print $2}' <<<"${MODELINE}" | tr -d '"'
  66. )"
  67. if [[ "${VIDEO_PORT,,}" == "none" ]]; then
  68. CONNECTED_MONITOR=(--use-display-device=None)
  69. else
  70. CONNECTED_MONITOR=(--connected-monitor="${VIDEO_PORT}")
  71. fi
  72. echo "[desktop] Generating /etc/X11/xorg.conf for ${DISPLAY_SIZEW}x${DISPLAY_SIZEH}@${DISPLAY_REFRESH}..."
  73. sudo rm -f /etc/X11/xorg.conf
  74. sudo nvidia-xconfig --virtual="${DISPLAY_SIZEW}x${DISPLAY_SIZEH}" --depth="${DISPLAY_CDEPTH}" --mode="${MODE_NAME}" --allow-empty-initial-configuration --no-probe-all-gpus --busid="${BUS_ID}" --include-implicit-metamodes --mode-debug --no-sli --no-base-mosaic --only-one-x-screen "${CONNECTED_MONITOR[@]}"
  75. sudo sed -i '/Driver[[:space:]]*"nvidia"/a\ Option "ModeValidation" "NoMaxPClkCheck,NoEdidMaxPClkCheck,NoMaxSizeCheck,NoHorizSyncCheck,NoVertRefreshCheck,NoVirtualSizeCheck,NoExtendedGpuCapabilitiesCheck,NoTotalSizeCheck,NoDualLinkDVICheck,NoDisplayPortBandwidthCheck,AllowNon3DVisionModes,AllowNonHDMI3DModes,AllowNonEdidModes,NoEdidHDMI2Check,AllowDpInterlaced"' /etc/X11/xorg.conf
  76. sudo sed -i '/Driver[[:space:]]*"nvidia"/a\ Option "AllowExternalGpus" "True"' /etc/X11/xorg.conf
  77. sudo sed -i '/Section[[:space:]]*"Monitor"/a\ '"${MODELINE}" /etc/X11/xorg.conf
  78. sudo sed -i '/"DPMS"/d' /etc/X11/xorg.conf
  79. sudo sed -i '/Section[[:space:]]*"Monitor"/a\ Option "DPMS" "False"' /etc/X11/xorg.conf
  80. cat <<'EOF' | sudo tee -a /etc/X11/xorg.conf >/dev/null
  81. Section "ServerFlags"
  82. Option "DontVTSwitch" "True"
  83. Option "DontZap" "True"
  84. Option "AllowMouseOpenFail" "True"
  85. Option "AutoAddGPU" "False"
  86. EndSection
  87. EOF
  88. # Xorg is started with -sharevts exactly like the previously validated stack.
  89. sudo ln -snf /dev/ptmx /dev/tty7
  90. echo "[desktop] Starting Xorg on ${DISPLAY}..."
  91. # Important:
  92. # Do not use udevadm trigger here. Sunshine input hotplug is handled by the
  93. # controlled Xorg restart in sunshine-entrypoint.sh.
  94. /usr/lib/xorg/Xorg "${DISPLAY}" vt7 -noreset -novtswitch -sharevts -nolisten tcp -ac -dpi "${DISPLAY_DPI}" +extension COMPOSITE +extension DAMAGE +extension GLX +extension RANDR +extension RENDER +extension MIT-SHM +extension XFIXES +extension XTEST &
  95. XORG_PID=$!
  96. echo "[desktop] Waiting for X socket..."
  97. for _ in $(seq 1 120); do
  98. if [[ -S "/tmp/.X11-unix/X${DISPLAY#:}" ]]; then
  99. break
  100. fi
  101. if ! kill -0 "${XORG_PID}" 2>/dev/null; then
  102. echo "[desktop] ERROR: Xorg exited before creating its socket." >&2
  103. wait "${XORG_PID}" || true
  104. exit 1
  105. fi
  106. sleep 0.5
  107. done
  108. if [[ ! -S "/tmp/.X11-unix/X${DISPLAY#:}" ]]; then
  109. echo "[desktop] ERROR: timed out waiting for Xorg." >&2
  110. exit 1
  111. fi
  112. echo "[desktop] Xorg is ready."
  113. xset -display "${DISPLAY}" -dpms 2>/dev/null || true
  114. xset -display "${DISPLAY}" s off 2>/dev/null || true
  115. xset -display "${DISPLAY}" s noblank 2>/dev/null || true
  116. export XDG_SESSION_ID="${DISPLAY#:}"
  117. export DESKTOP_SESSION=xfce
  118. export XDG_SESSION_DESKTOP=xfce
  119. export XDG_CURRENT_DESKTOP=XFCE
  120. export XDG_SESSION_TYPE=x11
  121. echo "[desktop] Starting XFCE..."
  122. xfce4-session &
  123. XFCE_PID=$!
  124. if ! pgrep -x steam >/dev/null 2>&1; then
  125. sleep 10
  126. echo "[desktop] Starting Steam in background..."
  127. steam -silent >/home/ubuntu/.steam-startup.log 2>&1 &
  128. fi
  129. # Keep the Supervisor program alive for the lifetime of the desktop session.
  130. wait "${XFCE_PID}"