mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 20:47:15 +01:00
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
The golden image logs in with agetty+startx and has no RGB controllers, no NVIDIA card and no sound card, so the night-lockdown scripts — which mask/stop lightdm.service and getty@.service and shell out to openrgb, nvidia-smi and amixer — had nothing real to act on in a sandbox and were being "verified" on the host instead. - `vm lightdm <name>`: installs lightdm + lightdm-gtk-greeter into the live overlay (pacman -Syu, not -S: the overlay's package database is the image's and mirrors have rotated those versions out), configures autologin -> i3 exactly like the host, turns tty1 back into a plain getty, reboots the guest and proves lightdm.service is active with an Xorg it owns. Never rebuilds the base: `vm build --force` re-seals a new checksum while every existing sandbox still backs onto the old file's name, which is silent qcow2 corruption. - `vm shim <name> <tool> [exit[:N]|hang|sleep:S]`: a fake tool ahead of the real one on PATH, every call logged with an epoch to /var/log/vmbox-shim/<tool>.log so the host can assert what ran and in what order. `hang` is the openrgb 1.0-2 that never returned on 2026-09-12 and defeated the curfew. - The DISPLAY/XAUTHORITY resolver `vm run` sources becomes its own file, guest/vmbox-x11.sh, installed by the image build and re-installed by the lightdm switch; it now tests readability, not existence, and tries ~/.Xauthority before the startx serverauth glob, because lightdm's Xorg -auth file is root-only. - README: the worked example uses MIDNIGHT_SHUTDOWN_CONFIRM=y (the installer refuses to run unattended now; `echo y |` no longer works), and the "i2c RGB stays on the host" line is gone. - bats: four host-side tests for shim.sh (exit, exit:N, hang, refusals). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015mLnUeoJ3mUwGRTowTUH6d
89 lines
3.7 KiB
Bash
89 lines
3.7 KiB
Bash
#!/bin/bash
|
|
# ============================================================================
|
|
# vmbox: make a sandbox look like the host where the base image cannot.
|
|
#
|
|
# vm lightdm <name> lightdm autologin -> i3, tty1 a plain getty
|
|
# vm shim <name> <tool> [mode] fake a hardware tool (openrgb, nvidia-smi)
|
|
#
|
|
# Both mutate a live overlay and are undone by `vm reset`. Neither touches the
|
|
# golden image: rebuilding it would silently corrupt every existing sandbox.
|
|
# ============================================================================
|
|
|
|
# shellcheck source=common.sh
|
|
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
|
|
source "$(dirname "${BASH_SOURCE[0]}")/ssh.sh"
|
|
source "$(dirname "${BASH_SOURCE[0]}")/launch.sh"
|
|
|
|
readonly DESKTOP_REBOOT_SSH_TIMEOUT="${VMBOX_DESKTOP_REBOOT_SSH_TIMEOUT:-150}"
|
|
|
|
_desktop_ensure_running() {
|
|
local name="$1"
|
|
if ! vm_is_running "$name"; then
|
|
launch_vm "$name" >/dev/null
|
|
vm_wait_ssh "$name" 150 || die "sandbox '$name' did not become reachable"
|
|
fi
|
|
}
|
|
|
|
# Copy a guest/ script (plus any siblings it needs) in and run it as root.
|
|
_desktop_run_guest_script() {
|
|
local name="$1" script="$2"; shift 2
|
|
local f
|
|
for f in "$script" "$@"; do
|
|
vm_scp_to "$name" "$VMBOX_GUEST_DIR/$f" "/tmp/$f" ||
|
|
die "could not copy $f into '$name'"
|
|
done
|
|
vm_ssh_exec "$name" "chmod +x /tmp/$script && sudo /tmp/$script $VMBOX_GUEST_USER"
|
|
}
|
|
|
|
# vm lightdm <name>
|
|
cmd_lightdm() {
|
|
local name
|
|
name="$(validate_vm_name "${1:-}")"
|
|
require_vm "$name"
|
|
_desktop_ensure_running "$name"
|
|
|
|
log "Switching '$name' to lightdm autologin -> i3 (host topology)"
|
|
_desktop_run_guest_script "$name" desktop-lightdm.sh vmbox-x11.sh ||
|
|
die "lightdm switch failed in '$name'"
|
|
|
|
# The switch only takes effect on a fresh boot: lightdm must own the seat
|
|
# from the start, and the startx session on tty1 must never have run.
|
|
# -no-reboot makes a guest reboot exit qemu, so relaunch it ourselves.
|
|
log "Rebooting '$name' to bring lightdm up"
|
|
vm_ssh_exec "$name" "sudo systemctl reboot" >/dev/null 2>&1 || true
|
|
local waited=0
|
|
while vm_is_running "$name" && (( waited < 60 )); do
|
|
sleep 1; waited=$(( waited + 1 ))
|
|
done
|
|
vm_is_running "$name" && die "'$name' did not go down for the reboot"
|
|
launch_vm "$name" >/dev/null
|
|
vm_wait_ssh "$name" "$DESKTOP_REBOOT_SSH_TIMEOUT" ||
|
|
die "'$name' did not come back after the reboot"
|
|
|
|
# Prove the topology from the guest, not from the exit code: the unit is
|
|
# active AND an Xorg it owns is up -- that is what a lockdown script sees.
|
|
local state
|
|
state="$(vm_ssh_exec "$name" "export VMBOX_X_WAIT=45; . /etc/profile.d/vmbox-x11.sh; \
|
|
printf '%s %s %s' \"\$(systemctl is-active lightdm.service)\" \
|
|
\"\$(systemctl is-enabled getty@tty1.service 2>/dev/null || echo -)\" \"\${DISPLAY:-none}\"" 2>/dev/null)"
|
|
[[ "$state" == "active "*" :0" ]] ||
|
|
die "lightdm did not come up cleanly in '$name' (lightdm/getty@tty1/DISPLAY: $state)"
|
|
ok "'$name': lightdm.service active, autologin i3 session on ${state##* }"
|
|
}
|
|
|
|
# vm shim <name> <tool> [exit[:N]|hang|sleep:S]
|
|
cmd_shim() {
|
|
local name tool mode
|
|
name="$(validate_vm_name "${1:-}")"
|
|
tool="${2:-}"; mode="${3:-exit}"
|
|
[[ -n "$tool" ]] || die "usage: vm shim <name> <tool> [exit[:N]|hang|sleep:S]"
|
|
require_vm "$name"
|
|
_desktop_ensure_running "$name"
|
|
|
|
vm_scp_to "$name" "$VMBOX_GUEST_DIR/shim.sh" "/tmp/shim.sh" ||
|
|
die "could not copy shim.sh into '$name'"
|
|
vm_ssh_exec "$name" "chmod +x /tmp/shim.sh && sudo /tmp/shim.sh '$tool' '$mode'" ||
|
|
die "shim install failed in '$name'"
|
|
ok "'$name': $tool is now a shim ($mode); calls logged to /var/log/vmbox-shim/$tool.log"
|
|
}
|