From 6954333881aa7fecef59d69e59af86f16406807e Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 02:05:32 +1000 Subject: [PATCH 1/6] feat(ubuntu): add opt-in xrdp remote desktop script Provide LAN-scoped graphical remote access for Ubuntu without weakening the default install. Kept out of bootstrap.sh so the RDP listener only exists when explicitly requested, and restricted to the local subnet via ufw (allowing SSH before enabling, to avoid remote lockout). --- README.md | 17 +++ install/ubuntu/install-remote-desktop.sh | 132 +++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100755 install/ubuntu/install-remote-desktop.sh diff --git a/README.md b/README.md index b2520a6..b154809 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,23 @@ sudo scutil --set LocalHostName "$YOUR_HOSTNAME" - **Enable FileVault:** `sudo fdesetup enable` - **Disable Homebrew Analytics:** `brew analytics off` +### Remote Desktop (Ubuntu, optional) + +Not part of the default bootstrap. `install/ubuntu/install-remote-desktop.sh` +installs an XFCE desktop and an `xrdp` server, then restricts port 3389 to your +local subnet via `ufw` (allowing SSH first so it can't lock you out): + +```bash +bash install/ubuntu/install-remote-desktop.sh # interactive +bash install/ubuntu/install-remote-desktop.sh --yes # no prompt +SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh # override subnet +``` + +The subnet is auto-detected; override it with `SUBNET=` for multi-NIC +hosts. For an untrusted network, prefer an SSH tunnel over the LAN rule: +`ssh -L 3389:localhost:3389 user@host`, then connect your RDP client to +`localhost:3389`. + ## Platform Compatibility | Platform | Architecture | Status | diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh new file mode 100755 index 0000000..a6c191e --- /dev/null +++ b/install/ubuntu/install-remote-desktop.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# Opt-in Ubuntu remote desktop: XFCE + xrdp, LAN-scoped via ufw. +# +# NOT run by bootstrap.sh. Installs a graphical desktop and an RDP server, then +# restricts port 3389 to the local subnet. For untrusted networks prefer an SSH +# tunnel (ssh -L 3389:localhost:3389 user@host) over the LAN firewall rule. +# +# Usage: +# bash install/ubuntu/install-remote-desktop.sh # interactive +# bash install/ubuntu/install-remote-desktop.sh --yes # no prompt +# SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh +set -euo pipefail + +# Colors +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' +log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_err() { echo -e "${RED}[ERR ]${NC} $1" >&2; } + +ASSUME_YES=false +[[ "${1:-}" == "--yes" || "${1:-}" == "-y" ]] && ASSUME_YES=true + +# --- Guard: Ubuntu/apt only --- +if ! command -v apt-get &>/dev/null; then + log_err "This script targets Ubuntu (apt not found). Aborting." + exit 1 +fi + +# --- Resolve the interactive user (script calls sudo internally) --- +TARGET_USER="${SUDO_USER:-$USER}" +TARGET_HOME=$(getent passwd "$TARGET_USER" | cut -d: -f6) +if [[ -z "$TARGET_HOME" ]]; then + log_err "Could not resolve home directory for user '$TARGET_USER'." + exit 1 +fi + +# --- Detect LAN subnet (override with SUBNET=...) --- +if [[ -z "${SUBNET:-}" ]]; then + IFACE=$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}') + if [[ -n "$IFACE" ]]; then + SUBNET=$(ip route show dev "$IFACE" 2>/dev/null | awk '/proto kernel/ {print $1; exit}') + fi +fi +if [[ -z "${SUBNET:-}" ]]; then + log_err "Could not auto-detect the LAN subnet. Re-run with SUBNET=, e.g. SUBNET=192.168.1.0/24" + exit 1 +fi + +# --- Confirmation --- +log_warn "This installs a desktop (XFCE) and an RDP server (xrdp)." +log_warn "Port 3389/tcp will be opened to: ${SUBNET}" +log_warn "Desktop session will be configured for user: ${TARGET_USER}" +if [[ "$ASSUME_YES" != true ]]; then + read -r -p "Proceed? [y/N] " reply + [[ "$reply" =~ ^[Yy]$ ]] || { log_info "Aborted."; exit 0; } +fi + +# --- Desktop environment (XFCE: lightest, best xrdp compatibility) --- +log_info "Checking XFCE desktop..." +if dpkg -l xfce4 2>/dev/null | grep -q '^ii'; then + log_info "XFCE already installed." +else + log_info "Installing XFCE desktop (this pulls in several hundred MB)..." + sudo apt-get update + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xfce4 xfce4-goodies dbus-x11 + log_info "XFCE installed." +fi + +# --- xrdp --- +log_info "Checking xrdp..." +if command -v xrdp &>/dev/null; then + log_info "xrdp already installed." +else + log_info "Installing xrdp..." + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xrdp + log_info "xrdp installed." +fi + +# --- Session config: XFCE for the target user, cert group for xrdp --- +log_info "Configuring xrdp session for ${TARGET_USER}..." +if [[ -f "${TARGET_HOME}/.xsession" ]] && grep -q '^startxfce4' "${TARGET_HOME}/.xsession"; then + log_info ".xsession already set to startxfce4." +else + echo "startxfce4" | sudo tee "${TARGET_HOME}/.xsession" > /dev/null + sudo chown "${TARGET_USER}:${TARGET_USER}" "${TARGET_HOME}/.xsession" + log_info "Wrote ${TARGET_HOME}/.xsession" +fi +# Fixes black-screen-on-login from cert permission errors (idempotent). +sudo usermod -aG ssl-cert xrdp + +# --- Firewall: ufw, LAN-only, lockout-safe (allow SSH BEFORE enabling) --- +log_info "Configuring firewall (ufw)..." +if ! command -v ufw &>/dev/null; then + log_info "Installing ufw..." + sudo apt-get install -y ufw +fi +# Allow SSH first so enabling ufw can never strand a remote session. +sudo ufw allow 22/tcp comment 'SSH' > /dev/null +# Restrict RDP to the LAN subnet. +if sudo ufw status | grep -q "3389/tcp.*ALLOW.*${SUBNET}"; then + log_info "ufw rule for 3389 from ${SUBNET} already present." +else + sudo ufw allow from "${SUBNET}" to any port 3389 proto tcp comment 'xrdp LAN' > /dev/null + log_info "Allowed 3389/tcp from ${SUBNET}." +fi +if sudo ufw status | grep -q '^Status: active'; then + log_info "ufw already active." +else + sudo ufw --force enable + log_info "ufw enabled." +fi + +# --- Enable service --- +log_info "Enabling xrdp service..." +sudo systemctl enable --now xrdp +sudo systemctl restart xrdp + +# --- Summary --- +HOST_IP=$(ip -o -f inet addr show "${IFACE:-}" 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1) +echo +log_info "Remote desktop ready." +log_info " Service : $(systemctl is-active xrdp)" +log_info " Listen : 3389/tcp restricted to ${SUBNET}" +log_info " Connect : RDP client (Microsoft Remote Desktop / Remmina) -> ${HOST_IP:-}:3389" +log_info " Login : user '${TARGET_USER}' with its system password" +echo +log_info "To revert:" +log_info " sudo systemctl disable --now xrdp" +log_info " sudo ufw delete allow from ${SUBNET} to any port 3389 proto tcp" From 35a33ee4f4d9651d3f56d81df21016a52ac581d3 Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 02:48:54 +1000 Subject: [PATCH 2/6] feat(ubuntu): make remote desktop selectable, fix GNOME crashes XFCE installed alongside an existing GNOME caused session crashes. Support DESKTOP=gnome|xfce|auto (default to existing GNOME), configure an Xorg GNOME session for xrdp, and add a polkit override that silences the 24.04 colord authentication popups that destabilise remote sessions. --- README.md | 25 ++++-- install/ubuntu/install-remote-desktop.sh | 102 +++++++++++++++++++---- 2 files changed, 104 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b154809..a48f308 100644 --- a/README.md +++ b/README.md @@ -196,19 +196,32 @@ sudo scutil --set LocalHostName "$YOUR_HOSTNAME" ### Remote Desktop (Ubuntu, optional) Not part of the default bootstrap. `install/ubuntu/install-remote-desktop.sh` -installs an XFCE desktop and an `xrdp` server, then restricts port 3389 to your -local subnet via `ufw` (allowing SSH first so it can't lock you out): +sets up an `xrdp` server, then restricts port 3389 to your local subnet via +`ufw` (allowing SSH first so it can't lock you out): ```bash bash install/ubuntu/install-remote-desktop.sh # interactive bash install/ubuntu/install-remote-desktop.sh --yes # no prompt +DESKTOP=xfce bash install/ubuntu/install-remote-desktop.sh # force XFCE SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh # override subnet ``` -The subnet is auto-detected; override it with `SUBNET=` for multi-NIC -hosts. For an untrusted network, prefer an SSH tunnel over the LAN rule: -`ssh -L 3389:localhost:3389 user@host`, then connect your RDP client to -`localhost:3389`. +- **Desktop:** `DESKTOP=auto` (default) uses your existing GNOME if installed, + otherwise installs lightweight XFCE. Force one with `DESKTOP=gnome|xfce`. + On a machine you already run with GNOME, use GNOME to avoid two conflicting + desktops. +- **Subnet:** auto-detected; override with `SUBNET=` for multi-NIC hosts. +- **Polkit:** the script installs an override that silences the Ubuntu 24.04 + "authentication required to create a color profile" popups over RDP. +- **One session per user:** do not stay logged into the physical console as the + same user you RDP in as. GNOME/XFCE refuse two simultaneous sessions and you + get a black screen or crash (`loginctl list-sessions` to check). +- **GNOME black screen:** if the GNOME Xorg backend shows a black screen (a known + 24.04 bug), pick the `Xvnc` session from the xrdp login dropdown instead of + `Xorg`. +- **Untrusted network:** prefer an SSH tunnel over the LAN rule: + `ssh -L 3389:localhost:3389 user@host`, then point your RDP client at + `localhost:3389`. ## Platform Compatibility diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh index a6c191e..36f3438 100755 --- a/install/ubuntu/install-remote-desktop.sh +++ b/install/ubuntu/install-remote-desktop.sh @@ -5,9 +5,14 @@ # restricts port 3389 to the local subnet. For untrusted networks prefer an SSH # tunnel (ssh -L 3389:localhost:3389 user@host) over the LAN firewall rule. # +# Desktop is selectable via DESKTOP=gnome|xfce|auto (default auto: use GNOME if +# already installed, else install XFCE). On a machine you already use with GNOME, +# the GNOME path avoids running two conflicting desktop environments. +# # Usage: # bash install/ubuntu/install-remote-desktop.sh # interactive # bash install/ubuntu/install-remote-desktop.sh --yes # no prompt +# DESKTOP=xfce bash install/ubuntu/install-remote-desktop.sh # SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh set -euo pipefail @@ -49,24 +54,49 @@ if [[ -z "${SUBNET:-}" ]]; then exit 1 fi +# --- Choose desktop (DESKTOP=gnome|xfce|auto) --- +DESKTOP="${DESKTOP:-auto}" +if [[ "$DESKTOP" == "auto" ]]; then + if command -v gnome-session &>/dev/null; then + DESKTOP=gnome + else + DESKTOP=xfce + fi +fi +case "$DESKTOP" in + gnome|xfce) ;; + *) log_err "Invalid DESKTOP='${DESKTOP}'. Use gnome, xfce, or auto."; exit 1 ;; +esac +if [[ "$DESKTOP" == "gnome" ]] && ! command -v gnome-session &>/dev/null; then + log_err "DESKTOP=gnome but gnome-session is not installed." + log_err "Install GNOME first (e.g. sudo apt install ubuntu-desktop-minimal) or use DESKTOP=xfce." + exit 1 +fi + # --- Confirmation --- -log_warn "This installs a desktop (XFCE) and an RDP server (xrdp)." -log_warn "Port 3389/tcp will be opened to: ${SUBNET}" +log_warn "This sets up remote desktop using: ${DESKTOP^^}" +[[ "$DESKTOP" == "xfce" ]] && log_warn " XFCE will be installed (pulls in several hundred MB)." +[[ "$DESKTOP" == "gnome" ]] && log_warn " Uses your existing GNOME (no XFCE installed)." +log_warn "An RDP server (xrdp) will run, port 3389/tcp opened to: ${SUBNET}" log_warn "Desktop session will be configured for user: ${TARGET_USER}" if [[ "$ASSUME_YES" != true ]]; then read -r -p "Proceed? [y/N] " reply [[ "$reply" =~ ^[Yy]$ ]] || { log_info "Aborted."; exit 0; } fi -# --- Desktop environment (XFCE: lightest, best xrdp compatibility) --- -log_info "Checking XFCE desktop..." -if dpkg -l xfce4 2>/dev/null | grep -q '^ii'; then - log_info "XFCE already installed." +# --- Desktop environment --- +if [[ "$DESKTOP" == "xfce" ]]; then + log_info "Checking XFCE desktop..." + if dpkg -l xfce4 2>/dev/null | grep -q '^ii'; then + log_info "XFCE already installed." + else + log_info "Installing XFCE desktop (this pulls in several hundred MB)..." + sudo apt-get update + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xfce4 xfce4-goodies dbus-x11 + log_info "XFCE installed." + fi else - log_info "Installing XFCE desktop (this pulls in several hundred MB)..." - sudo apt-get update - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xfce4 xfce4-goodies dbus-x11 - log_info "XFCE installed." + log_info "Using existing GNOME desktop (no XFCE install)." fi # --- xrdp --- @@ -79,18 +109,47 @@ else log_info "xrdp installed." fi -# --- Session config: XFCE for the target user, cert group for xrdp --- -log_info "Configuring xrdp session for ${TARGET_USER}..." -if [[ -f "${TARGET_HOME}/.xsession" ]] && grep -q '^startxfce4' "${TARGET_HOME}/.xsession"; then - log_info ".xsession already set to startxfce4." +# --- Session config: write ~/.xsession for the chosen desktop --- +log_info "Configuring xrdp ${DESKTOP^^} session for ${TARGET_USER}..." +XS="${TARGET_HOME}/.xsession" +if [[ "$DESKTOP" == "gnome" ]]; then + # GNOME over xrdp must run an Xorg (not Wayland) session. + read -r -d '' XS_CONTENT <<'EOF' || true +export GNOME_SHELL_SESSION_MODE=ubuntu +export XDG_CURRENT_DESKTOP=ubuntu:GNOME +export XDG_SESSION_TYPE=x11 +exec /usr/bin/gnome-session +EOF else - echo "startxfce4" | sudo tee "${TARGET_HOME}/.xsession" > /dev/null - sudo chown "${TARGET_USER}:${TARGET_USER}" "${TARGET_HOME}/.xsession" - log_info "Wrote ${TARGET_HOME}/.xsession" + XS_CONTENT='exec startxfce4' +fi +if [[ -f "$XS" ]] && [[ "$(cat "$XS" 2>/dev/null)" == "$XS_CONTENT" ]]; then + log_info ".xsession already configured for ${DESKTOP}." +else + printf '%s\n' "$XS_CONTENT" | sudo tee "$XS" > /dev/null + sudo chown "${TARGET_USER}:${TARGET_USER}" "$XS" + log_info "Wrote ${XS}" fi # Fixes black-screen-on-login from cert permission errors (idempotent). sudo usermod -aG ssl-cert xrdp +# --- Polkit: stop the colord "authentication required" popups over RDP --- +# (Known Ubuntu 24.04 regression; affects GNOME and XFCE remote sessions alike.) +POLKIT_RULE=/etc/polkit-1/rules.d/45-allow-colord.rules +if [[ -f "$POLKIT_RULE" ]]; then + log_info "Polkit color-manager override already present." +else + log_info "Installing polkit override to suppress color-profile auth popups..." + sudo tee "$POLKIT_RULE" > /dev/null <<'EOF' +polkit.addRule(function(action, subject) { + if (action.id.indexOf("org.freedesktop.color-manager.") == 0) { + return polkit.Result.YES; + } +}); +EOF + sudo systemctl restart polkit 2>/dev/null || true +fi + # --- Firewall: ufw, LAN-only, lockout-safe (allow SSH BEFORE enabling) --- log_info "Configuring firewall (ufw)..." if ! command -v ufw &>/dev/null; then @@ -122,11 +181,20 @@ sudo systemctl restart xrdp HOST_IP=$(ip -o -f inet addr show "${IFACE:-}" 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1) echo log_info "Remote desktop ready." +log_info " Desktop : ${DESKTOP^^}" log_info " Service : $(systemctl is-active xrdp)" log_info " Listen : 3389/tcp restricted to ${SUBNET}" log_info " Connect : RDP client (Microsoft Remote Desktop / Remmina) -> ${HOST_IP:-}:3389" log_info " Login : user '${TARGET_USER}' with its system password" echo +log_warn "Do NOT be logged into the console as '${TARGET_USER}' at the same time:" +log_warn " GNOME/XFCE refuse two simultaneous sessions for one user (black screen/crash)." +log_warn " Check with: loginctl list-sessions" +if [[ "$DESKTOP" == "gnome" ]]; then + log_warn "If GNOME shows a black screen (a known 24.04 Xorg-backend bug), pick the" + log_warn " 'Xvnc' session from the dropdown on the xrdp login page instead of 'Xorg'." +fi +echo log_info "To revert:" log_info " sudo systemctl disable --now xrdp" log_info " sudo ufw delete allow from ${SUBNET} to any port 3389 proto tcp" From a74aa1e0d14a5c5a360db973daa85d6389ef92ba Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 03:23:02 +1000 Subject: [PATCH 3/6] fix(ubuntu): disable xorgxrdp glamor to stop black screen on weak GPUs On old/integrated GPUs xorgxrdp's glamor EGL shaders fail to compile, breaking the framebuffer path and producing a black screen. Force software rendering (DRMDevice/DRI3 off) for broad compatibility; document that GPU-less hosts must use XFCE since GNOME Shell cannot run on software GL. --- README.md | 9 ++++----- install/ubuntu/install-remote-desktop.sh | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a48f308..e7c51d7 100644 --- a/README.md +++ b/README.md @@ -208,17 +208,16 @@ SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh # override sub - **Desktop:** `DESKTOP=auto` (default) uses your existing GNOME if installed, otherwise installs lightweight XFCE. Force one with `DESKTOP=gnome|xfce`. - On a machine you already run with GNOME, use GNOME to avoid two conflicting - desktops. +- **GPU acceleration:** the script disables xorgxrdp glamor (forces software + rendering) so the X backend works on any GPU. On machines **without working + GPU acceleration** (old or integrated GPUs), GNOME Shell crashes on software + GL: use `DESKTOP=xfce`. Reserve GNOME for hosts with functioning GPU accel. - **Subnet:** auto-detected; override with `SUBNET=` for multi-NIC hosts. - **Polkit:** the script installs an override that silences the Ubuntu 24.04 "authentication required to create a color profile" popups over RDP. - **One session per user:** do not stay logged into the physical console as the same user you RDP in as. GNOME/XFCE refuse two simultaneous sessions and you get a black screen or crash (`loginctl list-sessions` to check). -- **GNOME black screen:** if the GNOME Xorg backend shows a black screen (a known - 24.04 bug), pick the `Xvnc` session from the xrdp login dropdown instead of - `Xorg`. - **Untrusted network:** prefer an SSH tunnel over the LAN rule: `ssh -L 3389:localhost:3389 user@host`, then point your RDP client at `localhost:3389`. diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh index 36f3438..715e595 100755 --- a/install/ubuntu/install-remote-desktop.sh +++ b/install/ubuntu/install-remote-desktop.sh @@ -109,6 +109,25 @@ else log_info "xrdp installed." fi +# --- Disable xorgxrdp glamor (GPU) acceleration for broad compatibility --- +# On old/integrated GPUs glamor's EGL shaders fail to compile, breaking the +# framebuffer-to-client path and producing a black screen. Forcing software +# rendering is rock-solid everywhere and the cost is negligible for a 2D desktop +# over LAN. +XORG_CONF=/etc/X11/xrdp/xorg.conf +if [[ -f "$XORG_CONF" ]]; then + if grep -q 'Option "DRMDevice" ""' "$XORG_CONF" && grep -q 'Option "DRI3" "0"' "$XORG_CONF"; then + log_info "xorgxrdp glamor already disabled." + else + log_info "Disabling xorgxrdp glamor (software rendering) for GPU compatibility..." + [[ -f "${XORG_CONF}.bak" ]] || sudo cp "$XORG_CONF" "${XORG_CONF}.bak" + sudo sed -i -E 's|(Option +"DRMDevice" +)"[^"]*"|\1""|; s|(Option +"DRI3" +)"[^"]*"|\1"0"|' "$XORG_CONF" + log_info "Glamor disabled in ${XORG_CONF}." + fi +else + log_warn "${XORG_CONF} not found; skipping glamor tweak." +fi + # --- Session config: write ~/.xsession for the chosen desktop --- log_info "Configuring xrdp ${DESKTOP^^} session for ${TARGET_USER}..." XS="${TARGET_HOME}/.xsession" From 3a71eda1b38f82910abdbe7fc4f233786b58211d Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 03:26:28 +1000 Subject: [PATCH 4/6] feat(ubuntu): default remote desktop to XFCE, GNOME opt-in XFCE is the reliable desktop over RDP (no GL compositing); GNOME Shell crashes on software-rendered GL. Make XFCE the default and require DESKTOP=gnome to opt in. --- README.md | 14 +++++++------- install/ubuntu/install-remote-desktop.sh | 23 ++++++++++------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e7c51d7..43e28a5 100644 --- a/README.md +++ b/README.md @@ -200,18 +200,18 @@ sets up an `xrdp` server, then restricts port 3389 to your local subnet via `ufw` (allowing SSH first so it can't lock you out): ```bash -bash install/ubuntu/install-remote-desktop.sh # interactive +bash install/ubuntu/install-remote-desktop.sh # interactive (XFCE) bash install/ubuntu/install-remote-desktop.sh --yes # no prompt -DESKTOP=xfce bash install/ubuntu/install-remote-desktop.sh # force XFCE +DESKTOP=gnome bash install/ubuntu/install-remote-desktop.sh # opt into GNOME SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh # override subnet ``` -- **Desktop:** `DESKTOP=auto` (default) uses your existing GNOME if installed, - otherwise installs lightweight XFCE. Force one with `DESKTOP=gnome|xfce`. +- **Desktop:** defaults to lightweight **XFCE** (most reliable over RDP). GNOME + is opt-in via `DESKTOP=gnome`. - **GPU acceleration:** the script disables xorgxrdp glamor (forces software - rendering) so the X backend works on any GPU. On machines **without working - GPU acceleration** (old or integrated GPUs), GNOME Shell crashes on software - GL: use `DESKTOP=xfce`. Reserve GNOME for hosts with functioning GPU accel. + rendering) so the X backend works on any GPU. GNOME Shell crashes on software + GL, so `DESKTOP=gnome` only works on hosts with functioning GPU acceleration; + everywhere else stick with the XFCE default. - **Subnet:** auto-detected; override with `SUBNET=` for multi-NIC hosts. - **Polkit:** the script installs an override that silences the Ubuntu 24.04 "authentication required to create a color profile" popups over RDP. diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh index 715e595..8dfd373 100755 --- a/install/ubuntu/install-remote-desktop.sh +++ b/install/ubuntu/install-remote-desktop.sh @@ -5,14 +5,14 @@ # restricts port 3389 to the local subnet. For untrusted networks prefer an SSH # tunnel (ssh -L 3389:localhost:3389 user@host) over the LAN firewall rule. # -# Desktop is selectable via DESKTOP=gnome|xfce|auto (default auto: use GNOME if -# already installed, else install XFCE). On a machine you already use with GNOME, -# the GNOME path avoids running two conflicting desktop environments. +# Desktop is selectable via DESKTOP=xfce|gnome|auto (default XFCE: most reliable +# over RDP). GNOME is opt-in (DESKTOP=gnome) and only works on hosts with usable +# GPU acceleration; it crashes on software-rendered GL. # # Usage: -# bash install/ubuntu/install-remote-desktop.sh # interactive +# bash install/ubuntu/install-remote-desktop.sh # interactive (XFCE) # bash install/ubuntu/install-remote-desktop.sh --yes # no prompt -# DESKTOP=xfce bash install/ubuntu/install-remote-desktop.sh +# DESKTOP=gnome bash install/ubuntu/install-remote-desktop.sh # SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh set -euo pipefail @@ -54,15 +54,12 @@ if [[ -z "${SUBNET:-}" ]]; then exit 1 fi -# --- Choose desktop (DESKTOP=gnome|xfce|auto) --- +# --- Choose desktop (DESKTOP=xfce|gnome|auto) --- +# Default to XFCE: it is the most reliable desktop over RDP (no GL compositing, +# works on software rendering). GNOME is opt-in via DESKTOP=gnome and only +# suitable on hosts with working GPU acceleration. DESKTOP="${DESKTOP:-auto}" -if [[ "$DESKTOP" == "auto" ]]; then - if command -v gnome-session &>/dev/null; then - DESKTOP=gnome - else - DESKTOP=xfce - fi -fi +[[ "$DESKTOP" == "auto" ]] && DESKTOP=xfce case "$DESKTOP" in gnome|xfce) ;; *) log_err "Invalid DESKTOP='${DESKTOP}'. Use gnome, xfce, or auto."; exit 1 ;; From 155beebe206725ee8fbdcd9fd9c33147baf44aee Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 03:47:03 +1000 Subject: [PATCH 5/6] feat(ubuntu): auto-unlock gnome-keyring for XFCE/xrdp sessions XFCE-over-xrdp starts no Secret Service, so Chromium/Electron apps warn the OS keyring is unavailable and fall back to plaintext storage. Install gnome-keyring and hook pam_gnome_keyring into xrdp-sesman (XFCE only, idempotent) so the keyring unlocks with the login password. --- install/ubuntu/install-remote-desktop.sh | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh index 8dfd373..057326f 100755 --- a/install/ubuntu/install-remote-desktop.sh +++ b/install/ubuntu/install-remote-desktop.sh @@ -92,6 +92,15 @@ if [[ "$DESKTOP" == "xfce" ]]; then sudo DEBIAN_FRONTEND=noninteractive apt-get install -y xfce4 xfce4-goodies dbus-x11 log_info "XFCE installed." fi + # XFCE has no Secret Service of its own; without one, Chromium/Electron apps + # warn the OS keyring is unavailable and fall back to plaintext storage. + if dpkg -l gnome-keyring 2>/dev/null | grep -q '^ii'; then + log_info "gnome-keyring already installed." + else + log_info "Installing gnome-keyring (Secret Service for XFCE)..." + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y gnome-keyring libsecret-1-0 seahorse + log_info "gnome-keyring installed." + fi else log_info "Using existing GNOME desktop (no XFCE install)." fi @@ -166,6 +175,29 @@ EOF sudo systemctl restart polkit 2>/dev/null || true fi +# --- gnome-keyring auto-unlock for XFCE/xrdp (Secret Service via PAM) --- +# GNOME console logins unlock the keyring via PAM; XFCE-over-xrdp does not, so +# Chromium/Electron apps fall back to plaintext storage. Hook pam_gnome_keyring +# into xrdp-sesman so the keyring unlocks with the login password. XFCE only; +# the GNOME path already handles its own keyring. +if [[ "$DESKTOP" == "xfce" ]]; then + PAM_FILE=/etc/pam.d/xrdp-sesman + if [[ -f "$PAM_FILE" ]] && grep -q 'pam_gnome_keyring.so' "$PAM_FILE"; then + log_info "pam_gnome_keyring already configured in ${PAM_FILE}." + elif [[ -f "$PAM_FILE" ]]; then + log_info "Adding pam_gnome_keyring hooks to ${PAM_FILE}..." + sudo tee -a "$PAM_FILE" > /dev/null <<'EOF' + +# gnome-keyring auto-unlock for remote (xrdp) sessions +auth optional pam_gnome_keyring.so +session optional pam_gnome_keyring.so auto_start +EOF + log_warn "Keyring auto-unlocks only if the keyring password matches the login password." + else + log_warn "${PAM_FILE} not found; skipping keyring PAM hook (is xrdp installed?)." + fi +fi + # --- Firewall: ufw, LAN-only, lockout-safe (allow SSH BEFORE enabling) --- log_info "Configuring firewall (ufw)..." if ! command -v ufw &>/dev/null; then @@ -210,6 +242,10 @@ if [[ "$DESKTOP" == "gnome" ]]; then log_warn "If GNOME shows a black screen (a known 24.04 Xorg-backend bug), pick the" log_warn " 'Xvnc' session from the dropdown on the xrdp login page instead of 'Xorg'." fi +if [[ "$DESKTOP" == "xfce" ]]; then + log_info "Keyring: unlocks automatically when its password matches the login password." + log_info " Restart already-running apps (or reconnect) for the keyring to take effect." +fi echo log_info "To revert:" log_info " sudo systemctl disable --now xrdp" From e42d8327e5480abba8dc0500f58dd17b238d1ad5 Mon Sep 17 00:00:00 2001 From: ns408 Date: Sun, 7 Jun 2026 04:23:19 +1000 Subject: [PATCH 6/6] feat(ubuntu): pin XFCE as default session manager (anti-GNOME-fallback) When ~/.xsession is missing or drifts, Ubuntu xrdp falls back to the system x-session-manager (GNOME), which black-screens on GPU-less hosts. Pin it to xfce4-session in the XFCE path so the fallback can never silently select GNOME. --- README.md | 4 ++++ install/ubuntu/install-remote-desktop.sh | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/README.md b/README.md index 43e28a5..99e87a2 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,10 @@ SUBNET=10.0.0.0/24 bash install/ubuntu/install-remote-desktop.sh # override sub rendering) so the X backend works on any GPU. GNOME Shell crashes on software GL, so `DESKTOP=gnome` only works on hosts with functioning GPU acceleration; everywhere else stick with the XFCE default. +- **Session fallback:** in the XFCE path the script pins the system default + session manager to XFCE. If `~/.xsession` ever goes missing, xrdp would + otherwise fall back to GNOME and black-screen/crash on a GPU-less host; pinning + prevents that silent fallback. - **Subnet:** auto-detected; override with `SUBNET=` for multi-NIC hosts. - **Polkit:** the script installs an override that silences the Ubuntu 24.04 "authentication required to create a color profile" popups over RDP. diff --git a/install/ubuntu/install-remote-desktop.sh b/install/ubuntu/install-remote-desktop.sh index 057326f..e63eb79 100755 --- a/install/ubuntu/install-remote-desktop.sh +++ b/install/ubuntu/install-remote-desktop.sh @@ -101,6 +101,19 @@ if [[ "$DESKTOP" == "xfce" ]]; then sudo DEBIAN_FRONTEND=noninteractive apt-get install -y gnome-keyring libsecret-1-0 seahorse log_info "gnome-keyring installed." fi + # Make XFCE the system default session manager. If ~/.xsession is ever missing + # or drifts, Ubuntu falls back to x-session-manager (GNOME by default), which + # crashes on GPUs without acceleration. Pin it to XFCE to prevent that silent + # fallback. (GDM console logins are unaffected; they pick the session directly.) + if command -v xfce4-session &>/dev/null && \ + update-alternatives --list x-session-manager 2>/dev/null | grep -qx /usr/bin/xfce4-session; then + if [[ "$(readlink -f /etc/alternatives/x-session-manager 2>/dev/null)" == /usr/bin/xfce4-session ]]; then + log_info "x-session-manager already defaults to XFCE." + else + log_info "Pinning x-session-manager default to XFCE (prevents GNOME fallback)..." + sudo update-alternatives --set x-session-manager /usr/bin/xfce4-session + fi + fi else log_info "Using existing GNOME desktop (no XFCE install)." fi