Section 17 was still labelled "XFCE + VNC" while the step it runs installs ubuntu-desktop and is guarded on it, so the heading described a setup the script had already stopped producing. Also spell out why setup-desktop.sh disables lightdm: it is not a display manager this script ever installs, it is residue on hosts set up by an earlier version that did install XFCE, and left enabled it beats GDM to the seat. Comments and one echo string; no behaviour change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
174 lines
8.1 KiB
Bash
Executable File
174 lines
8.1 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Officer Remote Desktop Setup — Ubuntu GNOME desktop on Xorg, mirrored over VNC.
|
|
#
|
|
# The platform mirrors the single physical display :0 with x11vnc (see vnc-manager.ts). x11vnc can only
|
|
# capture an Xorg server, NOT a Wayland compositor — so we install the full GNOME desktop but force GDM
|
|
# onto the Xorg session (WaylandEnable=false). Auto-login is enabled so a user session owns :0 for the
|
|
# mirror to attach to. Switching the display manager takes effect on the next reboot.
|
|
# Usage: ./scripts/setup-desktop.sh
|
|
|
|
echo "=== Officer Remote Desktop Setup (Ubuntu GNOME on Xorg) ==="
|
|
echo ""
|
|
|
|
DESKTOP_USER="$(whoami)"
|
|
|
|
# --- Step 1: Install GNOME desktop + GDM + x11vnc ---
|
|
echo "[1/6] Installing ubuntu-desktop, GDM, x11vnc..."
|
|
sudo apt update -qq
|
|
sudo DEBIAN_FRONTEND=noninteractive apt install -y -qq \
|
|
ubuntu-desktop \
|
|
gdm3 \
|
|
x11vnc \
|
|
dbus-x11
|
|
echo " Done."
|
|
# No tigervnc package is needed. The VNC sidecar writes the .vnc/passwd rfbauth file with
|
|
# `x11vnc -storepasswd` (see vnc-manager.ts). tigervnc-common was installed here for `vncpasswd`,
|
|
# but it does not ship that binary — it only provides tigervncconfig — so the rfbauth file was never
|
|
# created and the desktop could not authenticate.
|
|
|
|
# --- Step 2: Force GDM onto Xorg + enable auto-login (x11vnc cannot mirror Wayland) ---
|
|
echo "[2/6] Forcing Xorg session and auto-login in GDM..."
|
|
GDM_CONF=/etc/gdm3/custom.conf
|
|
sudo mkdir -p /etc/gdm3
|
|
[ -f "$GDM_CONF" ] || echo "[daemon]" | sudo tee "$GDM_CONF" > /dev/null
|
|
# Ensure a [daemon] section exists to anchor the keys under.
|
|
sudo grep -qE '^\[daemon\]' "$GDM_CONF" || echo "[daemon]" | sudo tee -a "$GDM_CONF" > /dev/null
|
|
|
|
# Set key=value under [daemon]: rewrite an existing (possibly commented) line, else insert after [daemon].
|
|
set_gdm_key() {
|
|
local key="$1" val="$2"
|
|
if sudo grep -qE "^[[:space:]]*#?[[:space:]]*${key}=" "$GDM_CONF"; then
|
|
sudo sed -i "s|^[[:space:]]*#\?[[:space:]]*${key}=.*|${key}=${val}|" "$GDM_CONF"
|
|
else
|
|
sudo sed -i "/^\[daemon\]/a ${key}=${val}" "$GDM_CONF"
|
|
fi
|
|
}
|
|
|
|
set_gdm_key WaylandEnable false
|
|
set_gdm_key AutomaticLoginEnable true
|
|
set_gdm_key AutomaticLogin "$DESKTOP_USER"
|
|
echo " Xorg forced (WaylandEnable=false), auto-login as $DESKTOP_USER."
|
|
|
|
# --- Step 3: Make GDM the default display manager ---
|
|
echo "[3/6] Setting GDM as the default display manager..."
|
|
echo "/usr/sbin/gdm3" | sudo tee /etc/X11/default-display-manager > /dev/null
|
|
sudo systemctl enable gdm3 >/dev/null 2>&1 || sudo systemctl enable gdm >/dev/null 2>&1 || true
|
|
sudo systemctl set-default graphical.target >/dev/null 2>&1 || true
|
|
# Disable any prior display manager so it doesn't fight GDM. lightdm is named because earlier versions
|
|
# of this script installed XFCE; a host set up back then still has it and it would win the boot race.
|
|
sudo systemctl disable lightdm >/dev/null 2>&1 || true
|
|
echo " Done (takes effect on next reboot)."
|
|
|
|
# --- Step 4: Install Brave browser (native .deb, not snap) ---
|
|
echo "[4/6] Installing Brave browser..."
|
|
if ! command -v brave-browser-stable > /dev/null 2>&1; then
|
|
sudo curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg \
|
|
https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg
|
|
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" \
|
|
| sudo tee /etc/apt/sources.list.d/brave-browser-release.list > /dev/null
|
|
sudo apt update -qq
|
|
sudo DEBIAN_FRONTEND=noninteractive apt install -y -qq brave-browser
|
|
fi
|
|
# Fix launcher symlink
|
|
if [ -f /opt/brave.com/brave/brave-browser ]; then
|
|
sudo rm -f /usr/bin/brave-browser-stable
|
|
sudo ln -s /opt/brave.com/brave/brave-browser /usr/bin/brave-browser-stable
|
|
fi
|
|
# Tell Brave to use basic password store (no keyring prompts)
|
|
sudo mkdir -p /etc/brave
|
|
echo '--password-store=basic' | sudo tee /etc/brave/brave-flags.conf > /dev/null
|
|
echo " Done."
|
|
|
|
# --- Step 5: Remove GNOME Keyring + set default browser (prevents password prompts on login) ---
|
|
echo "[5/6] Removing GNOME Keyring and setting default browser..."
|
|
sudo apt remove -y --purge gnome-keyring > /dev/null 2>&1 || true
|
|
rm -rf ~/.local/share/keyrings
|
|
if command -v brave-browser-stable > /dev/null 2>&1; then
|
|
sudo update-alternatives --set x-www-browser /opt/brave.com/brave/brave 2>/dev/null || true
|
|
echo " Brave set as default."
|
|
else
|
|
echo " No supported browser found, skipping default."
|
|
fi
|
|
|
|
# --- Step 6: Headless display (keep a desktop when no monitor is attached) ---
|
|
echo "[6/6] Configuring the headless display..."
|
|
|
|
# x11vnc mirrors :0, but with nothing plugged in the connector has no EDID and no CRTC, so GNOME
|
|
# renders nothing and the mirror is black. Replaying a real monitor's EDID makes the connector look
|
|
# permanently attached. The EDID has to be captured from a screen that is plugged in *now* — there is
|
|
# nothing to copy otherwise — so this step is skipped on a headless run and can be re-run later.
|
|
EDID_DIR=/lib/firmware/edid
|
|
EDID_FILE="$EDID_DIR/officer-screen.bin"
|
|
CONNECTED_SYSFS=""
|
|
for c in /sys/class/drm/card*-*/status; do
|
|
[ "$(cat "$c" 2>/dev/null)" = "connected" ] || continue
|
|
CONNECTED_SYSFS="$(basename "$(dirname "$c")")"
|
|
break
|
|
done
|
|
|
|
if [ -z "$CONNECTED_SYSFS" ] && [ ! -f "$EDID_FILE" ]; then
|
|
echo " ! No display connected and no EDID saved — skipping."
|
|
echo " Plug a monitor in and re-run this script to capture one, otherwise the remote"
|
|
echo " desktop will be black whenever nothing is attached."
|
|
else
|
|
# cardN-HDMI-A-1 -> HDMI-A-1, which is the name the kernel parameters use (card numbering can
|
|
# change between boots; the connector name does not).
|
|
if [ -n "$CONNECTED_SYSFS" ]; then
|
|
CONNECTOR="${CONNECTED_SYSFS#*-}"
|
|
sudo mkdir -p "$EDID_DIR"
|
|
sudo cp "/sys/class/drm/$CONNECTED_SYSFS/edid" "$EDID_FILE"
|
|
echo " Captured EDID from $CONNECTOR ($(stat -c%s "$EDID_FILE") bytes)."
|
|
echo "$CONNECTOR" | sudo tee "$EDID_DIR/officer-connector" > /dev/null
|
|
else
|
|
CONNECTOR="$(cat "$EDID_DIR/officer-connector" 2>/dev/null || echo HDMI-A-1)"
|
|
echo " Reusing the saved EDID for $CONNECTOR."
|
|
fi
|
|
|
|
# drm.edid_firmware makes the connector report that EDID; the trailing "e" on video= forces it
|
|
# enabled with nothing attached. amdgpu is not in the initramfs, so /lib/firmware is readable by
|
|
# the time the driver loads and no initramfs rebuild is needed.
|
|
KERNEL_ARGS="drm.edid_firmware=$CONNECTOR:edid/officer-screen.bin video=$CONNECTOR:1920x1080e"
|
|
if grep -q "drm.edid_firmware=" /etc/default/grub; then
|
|
echo " GRUB already carries a forced EDID — leaving it alone."
|
|
else
|
|
sudo cp /etc/default/grub "/etc/default/grub.bak-$(date +%Y%m%d%H%M%S)"
|
|
CURRENT=$(grep "^GRUB_CMDLINE_LINUX_DEFAULT=" /etc/default/grub | sed 's/^[^"]*"//; s/"$//')
|
|
sudo sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"${CURRENT:+$CURRENT }$KERNEL_ARGS\"|" /etc/default/grub
|
|
sudo update-grub > /dev/null 2>&1
|
|
echo " Added the forced EDID to the kernel command line (takes effect on reboot)."
|
|
fi
|
|
|
|
# The EDID's preferred mode is whatever the captured panel was, which may be small. GNOME picks
|
|
# preferred, so raise it at session start.
|
|
install -d "$HOME/.local/bin" "$HOME/.config/autostart"
|
|
install -m 755 "$(dirname "$0")/officer-set-display.sh" "$HOME/.local/bin/officer-set-display.sh"
|
|
cat > "$HOME/.config/autostart/officer-set-display.desktop" <<AUTOSTART
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=Officer display mode
|
|
Comment=Raise the headless display to its largest usable mode at login
|
|
Exec=$HOME/.local/bin/officer-set-display.sh
|
|
X-GNOME-Autostart-enabled=true
|
|
NoDisplay=true
|
|
AUTOSTART
|
|
echo " Installed the login-time mode setter."
|
|
fi
|
|
echo " Done."
|
|
|
|
# --- Cleanup old systemd service if it exists ---
|
|
if systemctl list-unit-files officer-vnc.service &>/dev/null; then
|
|
echo ""
|
|
echo "Removing old officer-vnc systemd service..."
|
|
sudo systemctl stop officer-vnc 2>/dev/null || true
|
|
sudo systemctl disable officer-vnc 2>/dev/null || true
|
|
sudo rm -f /etc/systemd/system/officer-vnc.service
|
|
sudo systemctl daemon-reload
|
|
echo " Done."
|
|
fi
|
|
|
|
echo ""
|
|
echo "Setup complete. The screen mirror (x11vnc on :0) is managed by the VNC sidecar."
|
|
echo "REBOOT to switch into the GNOME-on-Xorg session with auto-login."
|