`ci vmware` runs as ci-runner and relies on host-based X auth (xhost), but the grant is per-session and wiped on logout / X restart, so the GUI launch fails with "cannot open X display" after every desktop relogin. Add scripts/install-vmware-gui-access.sh: installs an XDG autostart entry in the desktop user's home that re-applies `xhost +SI:localuser:ci-runner` at each graphical login, and applies it immediately when a display is reachable. Desktop user resolves from --desktop-user / $CI_DESKTOP_USER / $SUDO_USER (never root); service user from $CI_RUN_USER. --uninstall removes the autostart entry and revokes the live grant. Wire it into setup-host-linux.sh as Step 8, with --desktop-user (default $SUDO_USER) and --skip-gui-access for headless hosts.
99 lines
4.2 KiB
Bash
Executable File
99 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# install-vmware-gui-access.sh — authorise the ci-runner service user on the
|
|
# desktop operator's X session so `ci vmware` can open the VMware Workstation
|
|
# GUI (the VM files are owned by ci-runner, mode 750, so the GUI must run as
|
|
# that user — see commands/vm.py:vmware).
|
|
#
|
|
# `ci vmware` runs as ci-runner and relies on host-based X auth (xhost). An
|
|
# xhost grant is runtime + per-session: it is wiped on logout / X restart. This
|
|
# script makes it persistent by installing a per-user XDG autostart entry in
|
|
# the *desktop* user's home that re-runs the grant at every graphical login. It
|
|
# also applies the grant immediately when a display is reachable, so no logout
|
|
# is needed the first time.
|
|
#
|
|
# Usage:
|
|
# ./scripts/install-vmware-gui-access.sh # desktop user = $SUDO_USER or $USER
|
|
# ./scripts/install-vmware-gui-access.sh --desktop-user simone
|
|
# ./scripts/install-vmware-gui-access.sh --uninstall
|
|
#
|
|
# Env:
|
|
# CI_RUN_USER service user to authorise (default: ci-runner)
|
|
# CI_DESKTOP_USER desktop user whose X session is granted (overridden by --desktop-user)
|
|
#
|
|
# Idempotent: re-running overwrites the autostart entry in place.
|
|
#
|
|
# Security note: `xhost +SI:localuser:<user>` grants that local user full
|
|
# access to the desktop X session (input injection, screen capture). Acceptable
|
|
# on a single-operator CI workstation. `SI:localuser:` is same-machine only,
|
|
# never network. Remove with --uninstall when no longer needed.
|
|
set -euo pipefail
|
|
|
|
RUN_USER="${CI_RUN_USER:-ci-runner}"
|
|
DESKTOP_USER="${CI_DESKTOP_USER:-}"
|
|
ACTION="install"
|
|
|
|
log() { printf '[install-vmware-gui-access] %s\n' "$*"; }
|
|
die() { printf '[install-vmware-gui-access] ERROR: %s\n' "$*" >&2; exit 1; }
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--desktop-user) DESKTOP_USER="${2:-}"; shift 2 ;;
|
|
--uninstall) ACTION="uninstall"; shift ;;
|
|
-h|--help) sed -n '2,30p' "$0"; exit 0 ;;
|
|
*) die "unknown argument: $1 (use --desktop-user <name> or --uninstall)" ;;
|
|
esac
|
|
done
|
|
|
|
# Resolve the desktop user: explicit flag/env, else the user behind sudo, else
|
|
# the current user. Never default to root — root has no graphical session.
|
|
if [ -z "$DESKTOP_USER" ]; then
|
|
DESKTOP_USER="${SUDO_USER:-$USER}"
|
|
fi
|
|
[ -z "$DESKTOP_USER" ] && die "could not determine desktop user (pass --desktop-user <name>)"
|
|
[ "$DESKTOP_USER" = "root" ] && die "desktop user resolved to root; pass --desktop-user <name>"
|
|
|
|
id "$DESKTOP_USER" &>/dev/null || die "desktop user '$DESKTOP_USER' does not exist"
|
|
id "$RUN_USER" &>/dev/null || log "WARNING: service user '$RUN_USER' does not exist yet — grant installed anyway."
|
|
|
|
HOME_DIR="$(getent passwd "$DESKTOP_USER" | cut -d: -f6)"
|
|
[ -n "$HOME_DIR" ] && [ -d "$HOME_DIR" ] || die "home directory for '$DESKTOP_USER' not found"
|
|
|
|
AUTOSTART_DIR="$HOME_DIR/.config/autostart"
|
|
DESKTOP_FILE="$AUTOSTART_DIR/ci-runner-xhost.desktop"
|
|
GRANT="SI:localuser:$RUN_USER"
|
|
|
|
# Run a command as the desktop user, preserving ownership of created files.
|
|
as_desktop() { sudo -u "$DESKTOP_USER" "$@"; }
|
|
|
|
if [ "$ACTION" = "uninstall" ]; then
|
|
as_desktop rm -f "$DESKTOP_FILE" && log "removed $DESKTOP_FILE"
|
|
# Best-effort: revoke the live grant too (ignore failure when no display).
|
|
as_desktop xhost "-$GRANT" >/dev/null 2>&1 && log "revoked live grant ($GRANT)" || true
|
|
log "done."
|
|
exit 0
|
|
fi
|
|
|
|
# Install the autostart entry, owned by the desktop user.
|
|
as_desktop mkdir -p "$AUTOSTART_DIR"
|
|
as_desktop tee "$DESKTOP_FILE" >/dev/null <<EOF
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=Authorise $RUN_USER on X (CI vmware GUI)
|
|
Comment=Grant the $RUN_USER service user access to this X session so 'ci vmware' can open the VMware Workstation GUI
|
|
Exec=xhost +$GRANT
|
|
X-GNOME-Autostart-enabled=true
|
|
NoDisplay=true
|
|
EOF
|
|
as_desktop chmod 0644 "$DESKTOP_FILE"
|
|
log "installed $DESKTOP_FILE (re-applies at each graphical login)"
|
|
|
|
# Apply immediately if a display is reachable now, so no logout is needed.
|
|
DESKTOP_DISPLAY="${DISPLAY:-:0}"
|
|
if as_desktop env DISPLAY="$DESKTOP_DISPLAY" xhost "+$GRANT" >/dev/null 2>&1; then
|
|
log "applied now on display $DESKTOP_DISPLAY ($GRANT)"
|
|
else
|
|
log "could not apply now (no reachable display) — takes effect at next login of '$DESKTOP_USER'"
|
|
fi
|
|
|
|
log "done. Test with: ci vmware"
|