#!/usr/bin/env bash # Bureau Linux distant sur le pod : Xvfb + x11vnc + noVNC + XFCE, dans le navigateur. # # Cette pile n'est pas inventee ici : elle reprend celle du Space patdev/prime, # deja eprouvee. Les details qui comptent, et pourquoi : # xfwm4 sans gestionnaire de fenetres, les dialogues modaux ne prennent # pas le focus et les menus passent derriere leur parent # dbus-x11 sans bus de session, les applications GTK demarrent tres # lentement ou refusent de demarrer # -noxdamage obligatoire avec Xvfb (l'extension DAMAGE y est incomplete) # -wait/-defer limitation du taux de rafraichissement : rend le bureau # utilisable a distance au lieu de saturer le lien # -localhost x11vnc n'ecoute QUE sur la loopback ; tout passe par websockify # xset s off sinon l'economiseur d'ecran est indistinguable d'un bureau plante # superviseur XFCE se relance seul s'il meurt, sinon un plantage laisse un # fond d'ecran vide sans aucun message # # websockify sert lui-meme les fichiers noVNC : pas besoin de nginx. # Le port 6080 est expose en HTTP par Runpod, donc aucun client VNC necessaire. set -uo pipefail export DEBIAN_FRONTEND=noninteractive export DISPLAY="${VL_DESKTOP_DISPLAY:-:1}" GEO="${VL_DESKTOP_GEO:-1920x1080}" MDP="${VNC_PASSWORD:-SECRET}" # defaut demande ; VNC_PASSWORD="" pour ouvrir sans mot de passe LOG=/tmp/desktop.log log() { echo "[bureau] $(date +%H:%M:%S) $*" | tee -a "$LOG"; } if ! command -v x11vnc >/dev/null 2>&1; then log "installation ..." # x11vnc / novnc / websockify vivent dans "universe" sur Ubuntu grep -q "^deb .* universe" /etc/apt/sources.list /etc/apt/sources.list.d/* 2>/dev/null \ || (command -v add-apt-repository >/dev/null 2>&1 && add-apt-repository -y universe >>"$LOG" 2>&1) || true apt-get update -qq >>"$LOG" 2>&1 apt-get install -y -qq --no-install-recommends \ xvfb x11vnc novnc websockify x11-utils x11-xserver-utils xauth dbus-x11 \ xfwm4 xfce4-session xfce4-panel xfce4-terminal xfdesktop4 xfconf thunar \ fonts-dejavu-core adwaita-icon-theme \ >>"$LOG" 2>&1 || { log "ECHEC apt (voir $LOG)"; exit 1; } log "installation terminee" else log "deja installe" fi export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp/runtime-root}" mkdir -p "$XDG_RUNTIME_DIR" && chmod 700 "$XDG_RUNTIME_DIR" mkdir -p /tmp/.X11-unix && chmod 1777 /tmp/.X11-unix pkill -f "Xvfb $DISPLAY" 2>/dev/null; pkill -f "x11vnc .*-rfbport 5900" 2>/dev/null pkill -f "websockify.*6080" 2>/dev/null; pkill -f "bureau_superviseur" 2>/dev/null sleep 1; rm -f "/tmp/.X11-unix/X${DISPLAY#:}" "/tmp/.X${DISPLAY#:}-lock" 2>/dev/null log "Xvfb $DISPLAY en ${GEO}x24" Xvfb "$DISPLAY" -screen 0 "${GEO}x24" -ac +extension GLX +render -noreset >/tmp/xvfb.log 2>&1 & for _ in $(seq 1 100); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; sleep .1; done xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { log "ECHEC : Xvfb ne repond pas"; tail -5 /tmp/xvfb.log; exit 1; } xset -display "$DISPLAY" s off; xset -display "$DISPLAY" -dpms 2>/dev/null ARGS=(-display "$DISPLAY" -forever -shared -rfbport 5900 -localhost -noxdamage -repeat -xkb -wait 10 -defer 10 -nowf -noscr) if [ -n "$MDP" ]; then mkdir -p /root/.vnc; x11vnc -storepasswd "$MDP" /root/.vnc/passwd >/dev/null 2>&1 ARGS+=( -rfbauth /root/.vnc/passwd ); log "mot de passe VNC actif" else ARGS+=( -nopw ) fi log "x11vnc sur 5900 (loopback)" x11vnc "${ARGS[@]}" >/tmp/x11vnc.log 2>&1 & WEB=/usr/share/novnc [ -f "$WEB/vnc.html" ] && [ ! -e "$WEB/index.html" ] && ln -sf vnc.html "$WEB/index.html" log "noVNC sur 6080" websockify --web="$WEB" 0.0.0.0:6080 127.0.0.1:5900 >/tmp/novnc.log 2>&1 & # XFCE, relance automatique : un plantage silencieux laisserait un ecran vide. bureau_superviseur() { while true; do DISPLAY="$DISPLAY" dbus-run-session -- startxfce4 >/tmp/xfce.log 2>&1 || true echo "[bureau] session XFCE terminee, relance" >>"$LOG" sleep 2 done } bureau_superviseur & disown sleep 4 x=$(pgrep -c -f "Xvfb $DISPLAY" || true); v=$(pgrep -c -f "x11vnc .*5900" || true) w=$(pgrep -c -f "websockify.*6080" || true); f=$(pgrep -c -f xfwm4 || true) log "Xvfb=$x x11vnc=$v websockify=$w xfwm4=$f" if [ "$x" -ge 1 ] && [ "$v" -ge 1 ] && [ "$w" -ge 1 ]; then log "BUREAU PRET -> https://-6080.proxy.runpod.net/vnc.html?autoconnect=1&resize=remote" else log "ECHEC : voir /tmp/xvfb.log /tmp/x11vnc.log /tmp/novnc.log /tmp/xfce.log" fi