fix: Add CachyOS test VM dev environment and VM testing skill

QEMU/KVM scripts for a CachyOS KDE test VM (run.sh/run.ps1, get-iso,
guest SSH setup), host helper scripts to drive and inspect the
cachyos-gamescope-boot wizard in the guest, and a Claude Code skill
documenting the test workflow.
This commit is contained in:
theupriser committed 2026-09-23 15:14:17 +02:00
commit 97c5c569c8
13 files changed
+562

No files matched your search

+204
View File
@@ -0,0 +1,204 @@
---
name: cachyos-vm-testing
description: Use when testing cachyos-gamescope-boot (setup-gamescope-boot.sh) changes in the CachyOS QEMU test VM - starting/stopping the VM, restoring snapshots, running the wizard over SSH with scripted menu input, checking each component's state, reboot checks and screenshots.
---
# Testing cachyos-gamescope-boot in the CachyOS VM
The wizard (`setup-gamescope-boot.sh` + `lib/*.sh`) opens a menu that detects
which components are on and toggles them to match the user's choice. Menu order:
1. SteamOS conversion (boot into gaming mode via autologin, Return to Gaming Mode shortcut, Steam desktop autostart)
2. SteamOS theme (Vapor)
3. Steam Deck/Machine icons (`STEAM_GAMEPADUI_ARGS -steamos3`)
4. Single user mode (SDDM, no lock screen/user switching/log out; enabling it enables 1, disabling 1 disables it)
5. Steam Machine support (only on DMI Valve/Fremont: leds-valve-dkms-git, udev rule, steamos-manager)
Undo journals live in `~/.local/state/cachyos-gamescope-boot/` in the guest.
Run everything from the root of this repo on the host. Defaults: user
`theupriser`, SSH port `2222` (the scripts take `VM_USER` / `VM_PORT` / `VM_HOST`).
## VM lifecycle
Start in the background:
```bash
./run.sh --fremont > /tmp/vm.log 2>&1 & # flags: [install] [--fremont] [--nvidia] [--vulkan]
```
Wait for SSH:
```bash
until ssh -p 2222 -o BatchMode=yes -o ConnectTimeout=3 theupriser@localhost true 2>/dev/null; do sleep 3; done
```
Shut down and wait until QEMU is gone. Use `'^qemu-system'`: a plain
`pgrep -f qemu-system` also matches the shell running it.
```bash
ssh -p 2222 -o BatchMode=yes theupriser@localhost sudo systemctl poweroff
while pgrep -f '^qemu-system' >/dev/null; do sleep 2; done
```
## Snapshots
Only while the VM is off. Keep vars.fd together with the disk.
```bash
qemu-img snapshot -l disk.qcow2 # list
qemu-img snapshot -a ssh-ready disk.qcow2 && cp vars.ssh-ready.fd vars.fd # restore
qemu-img snapshot -c my-state disk.qcow2 && cp vars.fd vars.my-state.fd # create
```
Existing snapshots: `clean` (fresh install) and `ssh-ready` (sshd + host key +
passwordless sudo). Reset to `ssh-ready` before each full test run.
## First-time guest setup
Only when building from `clean`. In the guest console:
```bash
sudo mount -t 9p -o trans=virtio,version=9p2000.L vmtools /media && /media/guest-ssh-setup.sh
```
This installs and enables sshd, opens the firewall (ufw/firewalld if active),
adds the host keys (`share/host-keys.pub`, written by `run.sh`) and a NOPASSWD
sudoers rule for the test user.
## Mounting the project repo
The repo (`REPO`, default `~/projects/cachyos-gamescope-boot`) is shared
read-write as 9p tag `repo`. The `ssh-ready` snapshot does not mount it:
```bash
ssh -p 2222 -o BatchMode=yes theupriser@localhost bash -s << 'EOF'
sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
# optional, survives reboots:
grep -q ' /mnt 9p ' /etc/fstab || echo 'repo /mnt 9p trans=virtio,version=9p2000.L,nofail 0 0' | sudo tee -a /etc/fstab
EOF
```
## Remote commands: the guest shell is fish
Pass remote commands as bash heredocs, never as inline strings containing `$`:
```bash
ssh -p 2222 -o BatchMode=yes theupriser@localhost bash -s << 'EOF'
echo "$HOME"
EOF
```
## Getting a Plasma session
On a fresh snapshot the plasmalogin greeter is shown. Enable test autologin:
```bash
ssh -p 2222 -o BatchMode=yes theupriser@localhost bash -s << 'EOF'
sudo mkdir -p /etc/plasmalogin.conf.d
printf '[Autologin]\nUser=theupriser\nSession=plasma.desktop\n' | sudo tee /etc/plasmalogin.conf.d/00-test-autologin.conf
sudo systemctl restart plasmalogin
EOF
```
Remove `/etc/plasmalogin.conf.d/00-test-autologin.conf` before testing the
"normal login screen" case.
## Running the wizard non-interactively
`scripts/vmrun.sh '<input>'` does this (log also at `/tmp/wizard.log` in the
guest). Manually, in the guest:
```bash
export XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
printf '\ny\nn\n' | /mnt/setup-gamescope-boot.sh
```
Menu input: a number toggles a component, an empty line continues, `a`
re-applies what is on, `q` quits. Then `y` answers "Go ahead?" and `n` the
restart question.
| Input | Meaning |
|---|---|
| `'\ny\nn\n'` | first run, accept all |
| `'2\n\ny\nn\n'` | toggle the theme |
| `'a\ny\nn\n'` | re-apply what is on |
| `'q\n'` | just show the menu |
## Gamescope does not render in this VM
No suitable Vulkan (venus is unstable with the host NVIDIA driver). After
enabling the conversion, before rebooting:
```bash
sudo /usr/lib/steamos/steam-set-session plasma.desktop
```
so autologin lands in Plasma. Stuck in a gamescope relogin loop: over SSH set
the session to plasma and `sudo systemctl restart display-manager` (or stop the
DM, set the session, start it).
## Checking component state
`scripts/vmstate.sh` prints:
- display manager, SDDM autologin file, plasmalogin `[Autologin]` section
- session sync bridge units (`sync-steamos-session.path`) and sudoers rule (`gamescope-session-switch`)
- Return to Gaming Mode shortcut `Exec=` line
- `steam-desktop-autostart` user unit; glyphs env file (`99-gamescope-steam-glyphs.conf`)
- LookAndFeelPackage, ColorScheme, GTK theme, font
- KDE Action Restrictions (`lock_screen`), kscreenlockerrc Autolock, Lock Session shortcut
- panel floating/thickness in plasmashellrc
- kickoff `primaryActions` / `systemFavorites` / `icon`
- leds-valve-dkms-git package, udev rule, `leds_valve` module, `/sys/class/leds/valve-leds*` count and owner (user must be able to write)
- steamos-manager package and whether it is active
- undo journals present, and duplicate keys (`cut -f1-3 journal | sort | uniq -d`)
`scripts/cmp.sh save` stores a baseline of the KDE/GTK configs in the guest
(`~/.cache/vm-baseline`, not `/tmp`); `scripts/cmp.sh` diffs against it.
## Reboot checks
- Single user mode on: SDDM autologin without greeter: `pgrep sddm-greeter` empty, `plasmashell` running.
- Everything off: plasmalogin greeter shown: `loginctl list-sessions` shows a greeter session, no user `plasmashell`.
## Full test matrix
Reset to `ssh-ready`, start with `--fremont`, mount the repo, enable test
autologin, then (all passed last run; `scripts/vmstate.sh` after every step):
1. Fresh run turning everything on (`'\ny\nn\n'`), set session to plasma, reboot.
2. Rerun: all shown on, "Everything is already the way you want it".
3. `a` re-apply: no duplicate journal entries.
4. Theme off: look restored (CachyOS wallpaper, floating 30px panel, `org.cachyos.hello` launcher icon).
5. Single user off: switches to plasmalogin + sync bridge + sudoers; shortcut Exec uses `sudo -n`.
6. Single user on: back to SDDM.
7. Icons + Steam Machine support off: driver, udev rule, modules-load, steamos-manager removed; yay kept.
8. Conversion off: single user auto-unticked, plasmalogin `[Autologin]` back to CachyOS's `Session=plasma`, journals empty.
9. Remove the test autologin file, reboot: normal login screen.
## Visual checks
```bash
ssh -p 2222 -o BatchMode=yes theupriser@localhost bash -s << 'EOF'
export XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.activateLauncherMenu # optional, toggles
sleep 1; spectacle -b -n -f -o /tmp/x.png
EOF
scp -P 2222 theupriser@localhost:/tmp/x.png /tmp/x.png # then view it
```
The launcher call toggles; retake if the screenshot misses it. Apps started
directly over SSH lack the session's Qt platform theme and look light; start
them with `systemd-run --user <app>`.
## Pitfalls
- The guest's `/tmp` is cleared on reboot; keep baselines elsewhere.
- The fake Fremont DMI makes leds-valve load 17 LED nodes, but there is no real hardware.
- shellcheck: `sudo pacman -S shellcheck`, then in `/mnt`:
`shellcheck -S warning -x setup-gamescope-boot.sh lib/*.sh`
(SC2154/SC2034 cross-file warnings are false positives).
- This repo's `.gitignore` is an allowlist: it ignores everything and
un-ignores only the tracked scripts/docs. Add any new tracked file to it
explicitly, or git will silently ignore it.
+27
View File
@@ -0,0 +1,27 @@
# Allowlist: ignore everything, then un-ignore only scripts and docs.
# New tracked files must be added here explicitly.
/*
!/.gitignore
!/README.md
!/run.sh
!/run.ps1
!/get-iso.sh
!/get-iso.ps1
!/add-ssh-key.ps1
!/scripts/
!/share/
!/.claude/
share/*
!share/guest-ssh-setup.sh
# Belt and braces, anywhere in the tree
*.iso
*.iso.version
*.qcow2
*.img
*.fd
*.png
*.log
*.tmp
host-keys.pub
+83
View File
@@ -0,0 +1,83 @@
# cachyos-gamescope-boot dev environment
A QEMU/KVM test VM running CachyOS (KDE Plasma 6) for developing and testing
[cachyos-gamescope-boot](https://github.com/theupriser/cachyos-gamescope-boot),
plus helper scripts and a Claude Code skill that documents the test workflow.
Only scripts and docs live here. The ISO, disk image, UEFI variable stores,
logs and screenshots are generated locally. `.gitignore` is an allowlist: it
ignores everything and un-ignores only the tracked files, so add any new
tracked file to it explicitly.
## Requirements
- Linux host with KVM, `qemu-system-x86_64` (GTK/OpenGL display, virtfs/9p) and `qemu-img`
(Ubuntu: `sudo apt install qemu-system-x86 qemu-utils ovmf`).
- OVMF firmware at `/usr/share/OVMF/OVMF_CODE_4M.fd` and `OVMF_VARS_4M.fd`.
- `curl` and `sha256sum` for `get-iso.sh`.
- Optional: an NVIDIA dGPU for `--nvidia` (PRIME offload of the virgl renderer).
### Windows
`run.ps1` and `get-iso.ps1` are Windows versions. They need
[QEMU for Windows](https://qemu.weilnetz.de/w64/) (or set `QEMU_DIR`) and the
"Windows Hypervisor Platform" feature (`-accel whpx`). Windows QEMU has no 9p
shares: copy the repo into the guest with `scp -P 2222 -r ...`, and authorize
your key with `.\add-ssh-key.ps1 -User <vm-user>`.
## Quick start
```bash
./get-iso.sh # download and verify the latest CachyOS desktop ISO
./run.sh install # first run creates disk.qcow2 (60G) and vars.fd, boots the ISO
```
Install CachyOS with the **KDE Plasma** desktop and **plasma-login-manager**
as login manager. Power off and snapshot (only while the VM is off):
```bash
qemu-img snapshot -c clean disk.qcow2 && cp vars.fd vars.clean.fd
```
Boot the installed system (`./run.sh`) and, in the guest, enable SSH with key
auth and passwordless sudo through the read-only `vmtools` share:
```bash
sudo mount -t 9p -o trans=virtio,version=9p2000.L vmtools /media && /media/guest-ssh-setup.sh
```
Power off and snapshot again:
```bash
qemu-img snapshot -c ssh-ready disk.qcow2 && cp vars.fd vars.ssh-ready.fd
```
Connect with `ssh -p 2222 <user>@localhost`. The project repo is shared
read-write as 9p tag `repo`; in the guest:
`sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt`.
### run.sh options
```
[REPO=/path/to/cachyos-gamescope-boot] ./run.sh [install] [--nvidia] [--vulkan] [--fremont]
```
- `install`: boot the installer ISO
- `--nvidia`: render the guest's virtio-gpu (virgl) on the host NVIDIA dGPU
- `--vulkan`: expose Vulkan to the guest (venus; unstable)
- `--fremont`: fake the Valve Steam Machine (Fremont) DMI data via `-smbios`
- `REPO` defaults to `$HOME/projects/cachyos-gamescope-boot`
## Helper scripts
- `scripts/vmrun.sh '<menu input>'`: run the wizard in the guest's Plasma session with scripted input
- `scripts/vmstate.sh`: print the state of every wizard component
- `scripts/cmp.sh [save]`: save / diff the guest's KDE configs against a baseline
They use `VM_USER` (default `theupriser`), `VM_PORT` (`2222`) and `VM_HOST` (`localhost`).
## Claude Code skill
The full test workflow is documented in
[`.claude/skills/cachyos-vm-testing/SKILL.md`](.claude/skills/cachyos-vm-testing/SKILL.md);
Claude Code picks it up when run from this repo.
+9
View File
@@ -0,0 +1,9 @@
# Windows: authorize your SSH key in the VM (asks for the VM password once).
# Run after guest-ssh-setup.sh inside the VM, or at least after sshd is enabled there.
# .\add-ssh-key.ps1 -User <vm-user>
param([Parameter(Mandatory)][string]$User)
$ErrorActionPreference = 'Stop'
$key = Join-Path $env:USERPROFILE '.ssh\id_ed25519.pub'
if (-not (Test-Path $key)) { ssh-keygen -t ed25519 -f ($key -replace '\.pub$', '') -N '""' }
Get-Content $key | ssh -p 2222 "$User@localhost" 'install -d -m 700 ~/.ssh && k=$(cat) && (grep -qxF "$k" ~/.ssh/authorized_keys 2>/dev/null || echo "$k" >> ~/.ssh/authorized_keys) && chmod 600 ~/.ssh/authorized_keys'
Write-Host "Done. Connect with: ssh -p 2222 $User@localhost"
+28
View File
@@ -0,0 +1,28 @@
# Download the latest CachyOS desktop ISO to cachyos.iso and verify its checksum.
# Windows version of get-iso.sh; re-running resumes a partial download.
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
$mirror = if ($env:MIRROR) { $env:MIRROR } else { 'https://nl.mirror.cx/cachyos' }
$page = (Invoke-WebRequest -UseBasicParsing https://cachyos.org/download/).Content
$m = [regex]::Match($page, 'ISO/desktop/[0-9]+/cachyos-desktop-linux-[0-9]+\.iso')
if (-not $m.Success) { throw 'Could not find the current ISO on cachyos.org/download' }
$url = "$mirror/$($m.Value)"
$name = Split-Path $m.Value -Leaf
Write-Host "Latest release: $name"
if ((Test-Path cachyos.iso) -and ((Get-Content cachyos.iso.version -ErrorAction SilentlyContinue) -ne $name)) {
Write-Host 'Existing cachyos.iso is an older release, replacing it.'
Remove-Item cachyos.iso
}
# curl.exe ships with Windows 10+ and supports resuming (-C -).
curl.exe -fL -C - -o cachyos.iso $url
if ($LASTEXITCODE -ne 0) { throw 'Download failed' }
Set-Content cachyos.iso.version $name
Write-Host 'Verifying checksum...'
$expected = ((curl.exe -fsL "$url.sha256") -split '\s+')[0]
$actual = (Get-FileHash cachyos.iso -Algorithm SHA256).Hash
if ($actual -ieq $expected) { Write-Host 'cachyos.iso: OK' } else { throw "Checksum mismatch: $actual" }
Executable
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
# Download the latest CachyOS desktop ISO to cachyos.iso and verify its checksum.
# Re-running resumes a partial download; an up-to-date ISO is left alone.
set -euo pipefail
cd "$(dirname "$0")"
mirror="${MIRROR:-https://nl.mirror.cx/cachyos}"
# The download page embeds the current ISO URL; take the release from it.
release="$(curl -fsL https://cachyos.org/download/ |
grep -oE 'ISO/desktop/[0-9]+/cachyos-desktop-linux-[0-9]+\.iso' | head -n 1)"
if [[ -z "$release" ]]; then
echo "Could not find the current ISO on cachyos.org/download" >&2
exit 1
fi
url="$mirror/$release"
name="$(basename "$release")"
echo "Latest release: $name"
if [[ -f cachyos.iso && "$(cat cachyos.iso.version 2>/dev/null)" != "$name" ]]; then
echo "Existing cachyos.iso is an older release, replacing it."
rm -f cachyos.iso
fi
curl -fL -C - -o cachyos.iso "$url"
echo "$name" > cachyos.iso.version
echo "Verifying checksum..."
curl -fsL "$url.sha256" | awk '{print $1" cachyos.iso"}' | sha256sum -c
+29
View File
@@ -0,0 +1,29 @@
# CachyOS test VM for setup-gamescope-boot.sh -- Windows version.
# .\run.ps1 [-Install]
# Needs QEMU for Windows (https://qemu.weilnetz.de/w64/) and the Windows
# feature "Windows Hypervisor Platform" (for -accel whpx).
# Windows QEMU has no 9p shared folders: copy the repo in over SSH instead:
# scp -P 2222 -r ..\..\projects\cachyos-gamescope-boot <user>@localhost:
param([switch]$Install)
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
$qemuDir = if ($env:QEMU_DIR) { $env:QEMU_DIR } else { 'C:\Program Files\qemu' }
$qemu = Join-Path $qemuDir 'qemu-system-x86_64.exe'
$code = Join-Path $qemuDir 'share\edk2-x86_64-code.fd'
if (-not (Test-Path vars.fd)) { Copy-Item (Join-Path $qemuDir 'share\edk2-i386-vars.fd') vars.fd }
if (-not (Test-Path disk.qcow2)) { & (Join-Path $qemuDir 'qemu-img.exe') create -f qcow2 disk.qcow2 60G | Out-Null }
$qargs = @(
'-accel', 'whpx,kernel-irqchip=off', '-machine', 'q35', '-cpu', 'max', '-smp', '6', '-m', '8G',
'-drive', "if=pflash,format=raw,readonly=on,file=$code",
'-drive', 'if=pflash,format=raw,file=vars.fd',
'-drive', 'file=disk.qcow2,if=virtio',
'-device', 'virtio-vga,xres=1920,yres=1080', '-display', 'sdl',
'-device', 'qemu-xhci', '-device', 'usb-tablet',
'-nic', 'user,model=virtio-net-pci,hostfwd=tcp::2222-:22'
)
if ($Install) { $qargs += @('-cdrom', 'cachyos.iso', '-boot', 'd') }
& $qemu @qargs
Executable
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# CachyOS test VM for setup-gamescope-boot.sh.
# [REPO=/path/to/cachyos-gamescope-boot] ./run.sh [install] [--nvidia] [--vulkan] [--fremont]
# install boot the installer ISO
# --nvidia render the guest's virtio-gpu (virgl) on the host NVIDIA dGPU
# --vulkan expose Vulkan to the guest (venus; needed by gamescope, can be unstable)
# --fremont report the Valve Steam Machine's DMI data (for testing the wizard)
# REPO defaults to $HOME/projects/cachyos-gamescope-boot.
# The repo is shared into the guest; mount it there with:
# sudo mount -t 9p -o trans=virtio,version=9p2000.L repo /mnt
# First-time SSH setup, inside the guest:
# sudo mount -t 9p -o trans=virtio,version=9p2000.L vmtools /media && /media/guest-ssh-setup.sh
# SSH from the host: ssh -p 2222 <user>@localhost
cd "$(dirname "$0")"
repo="${REPO:-$HOME/projects/cachyos-gamescope-boot}"
cdrom=()
smbios=()
gpu=virtio-vga-gl,xres=1920,yres=1080
for arg in "$@"; do
case "$arg" in
install) cdrom=(-cdrom cachyos.iso -boot d) ;;
--nvidia) export __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia \
__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json ;;
--vulkan) gpu+=,hostmem=4G,blob=true,venus=true ;;
--fremont) smbios=(-smbios type=1,manufacturer=Valve,product=Fremont -smbios type=2,manufacturer=Valve,product=Fremont) ;;
*) echo "unknown argument: $arg" >&2; exit 1 ;;
esac
done
# First run: create the disk and the writable UEFI variable store.
[[ -f disk.qcow2 ]] || qemu-img create -f qcow2 disk.qcow2 60G
[[ -f vars.fd ]] || cp /usr/share/OVMF/OVMF_VARS_4M.fd vars.fd
# Hand the host's public keys to the guest setup script.
cat ~/.ssh/*.pub > share/host-keys.pub
exec qemu-system-x86_64 \
-enable-kvm -machine q35,memory-backend=mem -cpu host -smp 6 -m 8G \
-object memory-backend-memfd,id=mem,size=8G,share=on \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
-drive if=pflash,format=raw,file=vars.fd \
-drive file=disk.qcow2,if=virtio \
-device "$gpu" -display gtk,gl=on,zoom-to-fit=off \
-device qemu-xhci -device usb-tablet \
-nic user,model=virtio-net-pci,hostfwd=tcp::2222-:22 \
-virtfs local,path="$repo",mount_tag=repo,security_model=mapped-xattr \
-virtfs local,path="$PWD/share",mount_tag=vmtools,security_model=mapped-xattr,readonly=on \
"${smbios[@]}" "${cdrom[@]}"
Executable
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
# Diff the guest's KDE/GTK configs against a saved baseline.
# scripts/cmp.sh save copy the current ~/.config files to the baseline
# scripts/cmp.sh show differences against the baseline
# Env: VM_USER (theupriser), VM_PORT (2222), VM_HOST (localhost),
# BASELINE (guest dir, default ~/.cache/vm-baseline; not /tmp, which is cleared on reboot).
set -euo pipefail
. "$(dirname "$0")/common.sh"
mode="${1:-diff}"
# The guest login shell is fish, so pass values in through the bash script itself.
{ printf 'mode=%q base=%q\n' "$mode" "${BASELINE:-}"; cat << 'REMOTE'
base="${base:-$HOME/.cache/vm-baseline}"
files="kdeglobals plasmarc plasmashellrc kwinrc kwinrulesrc konsolerc kscreenlockerrc kglobalshortcutsrc gtk-3.0/settings.ini gtk-4.0/settings.ini plasma-org.kde.plasma.desktop-appletsrc"
if [ "$mode" = save ]; then
for f in $files; do mkdir -p "$(dirname "$base/config/$f")"; cp -f ~/.config/"$f" "$base/config/$f" 2>/dev/null || true; done
echo "baseline saved to $base"; exit 0
fi
noise='^(ColorSchemeHash|popupHeight|popupWidth|ItemGeometries|ItemGeometriesHorizontal|DialogHeight|DialogWidth|[0-9]+ screens: )'
for f in $files; do
d=$(diff <(sort -u "$base/config/$f" 2>/dev/null | grep -vE "$noise") <(sort -u ~/.config/"$f" 2>/dev/null | grep -vE "$noise") | grep '^[<>]' || true)
[ -n "$d" ] && { echo "== $f"; echo "$d" | head -25; }
done
echo "(end of diff)"
REMOTE
} | vm_ssh bash -s 2>&1
+5
View File
@@ -0,0 +1,5 @@
# Sourced by the other scripts: SSH target of the test VM.
VM_USER="${VM_USER:-theupriser}"
VM_PORT="${VM_PORT:-2222}"
VM_HOST="${VM_HOST:-localhost}"
vm_ssh() { ssh -p "$VM_PORT" -o BatchMode=yes "$VM_USER@$VM_HOST" "$@"; }
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Run the wizard inside the guest's Plasma session with scripted menu input.
# scripts/vmrun.sh '<menu input>' e.g. scripts/vmrun.sh '\ny\nn\n'
# Input is interpreted by printf: numbers toggle, empty line continues,
# a = re-apply, q = quit; then y for "Go ahead?" and n for the restart question.
# Env: VM_USER (theupriser), VM_PORT (2222), VM_HOST (localhost),
# GUEST_REPO (/mnt, where the repo is mounted in the guest), GUEST_UID (1000).
set -euo pipefail
. "$(dirname "$0")/common.sh"
input="${1:?usage: $0 '<menu input>'}"
GUEST_REPO="${GUEST_REPO:-/mnt}"
GUEST_UID="${GUEST_UID:-1000}"
# The guest login shell is fish, so pass values in through the bash script itself.
{ printf 'input=%q repo=%q uid=%q\n' "$input" "$GUEST_REPO" "$GUEST_UID"; cat << 'REMOTE'
export XDG_RUNTIME_DIR=/run/user/$uid WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$uid/bus
log=/tmp/wizard.log
# shellcheck disable=SC2059
printf "$input" | "$repo/setup-gamescope-boot.sh" > "$log" 2>&1; echo "exit=$?" >> "$log"
cat "$log"
REMOTE
} | vm_ssh bash -s 2>&1 | sed 's/\x1b\[[0-9;]*m//g'
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# Print the state of every wizard component in the guest.
# Env: VM_USER (theupriser), VM_PORT (2222), VM_HOST (localhost).
set -euo pipefail
. "$(dirname "$0")/common.sh"
vm_ssh bash -s << 'REMOTE' 2>&1
yn() { [ -e "$1" ] && echo y || echo n; }
echo "DM=$(systemctl show -p Id --value display-manager) sddm-autologin=$(yn /etc/sddm.conf.d/10-gamescope-autologin.conf) sync=$(yn /etc/systemd/system/sync-steamos-session.path) sudoers=$(sudo test -f /etc/sudoers.d/gamescope-session-switch && echo y || echo n)"
echo "plasmalogin [Autologin]: $(sed -n '/^\[Autologin\]/,/^\[/p' /etc/plasmalogin.conf | grep -v '^\[' | tr '\n' ' ')"
echo "shortcut=$(grep -h Exec= ~/Desktop/*Gaming*.desktop 2>/dev/null || echo none)"
echo "steam-unit=$([ -f ~/.config/systemd/user/steam-desktop-autostart.service ] && systemctl --user is-enabled steam-desktop-autostart.service || echo none) glyphs=$(yn ~/.config/environment.d/99-gamescope-steam-glyphs.conf)"
echo "lnf=$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage) scheme=$(kreadconfig6 --file kdeglobals --group General --key ColorScheme) gtk=$(kreadconfig6 --file ~/.config/gtk-3.0/settings.ini --group Settings --key gtk-theme-name) font=$(kreadconfig6 --file kdeglobals --group General --key font)"
echo "lock_screen=$(kreadconfig6 --file kdeglobals --group 'KDE Action Restrictions' --key action/lock_screen) autolock=$(kreadconfig6 --file kscreenlockerrc --group Daemon --key Autolock) metaL=$(kreadconfig6 --file kglobalshortcutsrc --group ksmserver --key 'Lock Session' | cut -c1-12)"
echo "panel: $(grep -A1 '^\[PlasmaViews\]\[Panel [0-9]*\]$' ~/.config/plasmashellrc | grep floating | tr '\n' ' ') $(grep -h 'thickness' ~/.config/plasmashellrc | tr '\n' ' ')"
echo "kickoff: $(grep -E '^(primaryActions|systemFavorites|icon)=' ~/.config/plasma-org.kde.plasma.desktop-appletsrc | tr '\n' ' ')"
echo "leds-pkg=$(pacman -Q leds-valve-dkms-git 2>/dev/null || echo none) steamos-manager=$(pacman -Q steamos-manager 2>/dev/null || echo none)/$(systemctl is-active steamos-manager 2>/dev/null) udev=$(yn /etc/udev/rules.d/70-valve-leds-user.rules) module=$(lsmod | grep -c leds_valve) leds=$(ls /sys/class/leds | grep -c valve)"
echo "leds-owner=$(stat -c %U /sys/class/leds/valve-leds*/brightness 2>/dev/null | sort -u | tr '\n' ' ')"
j=~/.local/state/cachyos-gamescope-boot
echo "journals: $(ls "$j" 2>/dev/null | tr '\n' ' ')"
for f in "$j"/*; do [ -f "$f" ] || continue; d=$(cut -f1-3 "$f" | sort | uniq -d); [ -n "$d" ] && echo "DUPLICATES in $(basename "$f"): $d"; done
true
REMOTE
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# Run INSIDE the VM (as your normal user) to make it reachable from the host
# over SSH with key auth and passwordless sudo:
# sudo mount -t 9p -o trans=virtio,version=9p2000.L vmtools /media && /media/guest-ssh-setup.sh
set -euo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
sudo pacman -S --needed --noconfirm openssh
sudo systemctl enable --now sshd
# Open port 22 if a firewall is active.
if command -v ufw >/dev/null && sudo ufw status | grep -q 'Status: active'; then
sudo ufw allow ssh
fi
if command -v firewall-cmd >/dev/null && sudo firewall-cmd --state >/dev/null 2>&1; then
sudo firewall-cmd --permanent --add-service=ssh && sudo firewall-cmd --reload
fi
# Authorize the host's key(s), without duplicates.
install -d -m 700 ~/.ssh
touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
while IFS= read -r key; do
[[ -n "$key" ]] && ! grep -qxF "$key" ~/.ssh/authorized_keys && echo "$key" >> ~/.ssh/authorized_keys
done < <(cat "$here/host-keys.pub" 2>/dev/null)
# Test VM only: passwordless sudo so the host can drive it non-interactively.
echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/99-test-vm >/dev/null
sudo chmod 440 /etc/sudoers.d/99-test-vm
echo "Done. From the host: ssh -p 2222 $USER@localhost"
[[ -s "$here/host-keys.pub" ]] || echo "No host keys were shared; add yours from the host (see add-ssh-key.ps1 on Windows)."