feat(setup): persist ci-runner X grant for ci vmware GUI
`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.
This commit is contained in:
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/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"
|
||||
Reference in New Issue
Block a user