From 4e7b18eb7d44c012fa6fe3daed4fbe8abe0c58ba Mon Sep 17 00:00:00 2001 From: Emir Beganovic Date: Fri, 9 Oct 2026 18:56:35 +0200 Subject: [PATCH] Scripts that turn an installed Omarchy disk into a downloadable VM image As they were tested by hand on the 4.0.4 ISO, before any of it is wired into a workflow: vm-install unattended install of an ISO into a qcow2, through cidata vm-seal makes the disk publishable: SSH takes keys only, no machine ID, host keys, build key or build logs left, compressed with zstd, with checksums and the kernel pulled out for direct boot vm-verify boots the sealed image once and checks all of that vm-boot boots a throwaway copy with a key made for that boot and runs a command in it On this machine: install 114 s, seal 27 s, a 4.2 GB image, SSH about 5 s after power-on, 17 of 17 verify checks, and 7 of them failing on an image sealed without these fixes. --- test/vm-image/vm-boot | 75 +++++++++++++++++++++ test/vm-image/vm-install | 90 +++++++++++++++++++++++++ test/vm-image/vm-seal | 142 +++++++++++++++++++++++++++++++++++++++ test/vm-image/vm-verify | 48 +++++++++++++ 4 files changed, 355 insertions(+) create mode 100755 test/vm-image/vm-boot create mode 100755 test/vm-image/vm-install create mode 100755 test/vm-image/vm-seal create mode 100755 test/vm-image/vm-verify diff --git a/test/vm-image/vm-boot b/test/vm-image/vm-boot new file mode 100755 index 0000000..86e059c --- /dev/null +++ b/test/vm-image/vm-boot @@ -0,0 +1,75 @@ +#!/bin/bash +# Boots a sealed Omarchy image (vm-seal) as a throwaway machine. +# +# vm-boot boot, print how to log in, run until Ctrl-C +# vm-boot boot, run the command over SSH, power off; +# exits with the command's status +# +# Nothing is written to sealed_dir: the machine runs on a copy-on-write overlay +# that is deleted on exit. Each boot gets a new SSH key and a new machine ID; +# the image itself holds no key and its SSH takes no password. +# +# Needs qemu-system-x86_64, qemu-img, ssh and a usable /dev/kvm. +# Env: SMP (4), MEM (4G), SSH_PORT (random), VM_UUID (random), APPEND (more +# kernel arguments), QEMU_EXTRA (more qemu arguments, split on spaces), +# VM_STATE_DIR (/var/tmp; holds the overlay, so it needs room to grow). +set -euo pipefail +[[ $# -ge 1 ]] || { sed -n '2,16p' "$0" >&2; exit 2; } +base=$(realpath "$1"); shift +for f in base.qcow2 vmlinuz initrd cmdline; do + [[ -s $base/$f ]] || { echo "vm-boot: $base/$f is missing" >&2; exit 1; } +done +[[ -r /dev/kvm && -w /dev/kvm ]] || { echo "vm-boot: /dev/kvm is not usable" >&2; exit 1; } + +state=$(mktemp -d "${VM_STATE_DIR:-/var/tmp}/vm.XXXXXX") +cleanup() { + local status=$? pid + if [[ -f $state/qemu.pid ]]; then + pid=$(cat "$state/qemu.pid") + kill "$pid" 2>/dev/null || true + for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done + fi + rm -rf "$state" + exit "$status" +} +trap cleanup EXIT +trap 'exit 130' INT TERM +port=${SSH_PORT:-$(( 20000 + RANDOM % 10000 ))} +uuid=${VM_UUID:-$(cat /proc/sys/kernel/random/uuid)} + +# A key made for this boot only, handed in through the firmware tables as a +# systemd credential that writes authorized_keys. +ssh-keygen -q -t ed25519 -N '' -C vm-boot -f "$state/id_ed25519" +keys=$(printf 'd /home/omarchy/.ssh 0700 omarchy omarchy -\nf+ /home/omarchy/.ssh/authorized_keys 0600 omarchy omarchy - %s\n' \ + "$(cat "$state/id_ed25519.pub")" | base64 -w0) +ssh_opts=(-i "$state/id_ed25519" -p "$port" -o BatchMode=yes -o IdentitiesOnly=yes + -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR) + +qemu-img create -qf qcow2 -b "$base/base.qcow2" -F qcow2 "$state/run.qcow2" +t0=$(date +%s%N) +# shellcheck disable=SC2086 +qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp "${SMP:-4}" -m "${MEM:-4G}" \ + -kernel "$base/vmlinuz" -initrd "$base/initrd" -append "$(cat "$base/cmdline")${APPEND:+ $APPEND}" \ + -uuid "$uuid" \ + -drive "file=$state/run.qcow2,format=qcow2,if=none,id=d0" -device virtio-blk-pci,drive=d0 \ + -smbios "type=11,value=io.systemd.credential.binary:tmpfiles.extra=$keys" \ + -device virtio-vga -device virtio-rng-pci -display none \ + -netdev "user,id=n0,hostfwd=tcp:127.0.0.1:$port-:22" -device virtio-net-pci,netdev=n0 \ + -qmp "unix:$state/qmp.sock,server,nowait" -pidfile "$state/qemu.pid" -daemonize ${QEMU_EXTRA:-} + +# /dev/null; do + kill -0 "$(cat "$state/qemu.pid")" 2>/dev/null || { echo "vm-boot: qemu exited before ssh came up" >&2; exit 1; } + (( ($(date +%s%N) - t0) / 1000000 < 300000 )) || { echo "vm-boot: no ssh after 300s" >&2; exit 1; } + sleep 0.2 +done +echo "vm-boot: ssh up after $(( ($(date +%s%N) - t0) / 1000000 )) ms, machine ID ${uuid//-/}" >&2 + +if [[ $# -gt 0 ]]; then + # Stdin passes through, so `vm-boot dir bash -s /dev/null; do sleep 1; done +fi diff --git a/test/vm-image/vm-install b/test/vm-image/vm-install new file mode 100755 index 0000000..ef63cd9 --- /dev/null +++ b/test/vm-image/vm-install @@ -0,0 +1,90 @@ +#!/bin/bash +# Unattended install of an Omarchy ISO into a qcow2, through a cidata drive. +# +# vm-install +# +# out_dir gets base.qcow2 (the installed disk, powered off), OVMF_VARS.4m.fd +# and the key that can log in to it. vm-seal turns that into a reusable image. +# Same answer files and VM shape as omarchy-iso's test/integration.d/base-test.sh. +set -uo pipefail +[[ $# -eq 2 ]] || { echo "Usage: vm-install " >&2; exit 2; } +ISO=$(realpath "$1"); OUT=$(realpath -m "$2"); W=$OUT/work +# Arch and Ubuntu keep the firmware in different places. +for fw in /usr/share/edk2/x64/OVMF_CODE.4m.fd:/usr/share/edk2/x64/OVMF_VARS.4m.fd /usr/share/OVMF/OVMF_CODE_4M.fd:/usr/share/OVMF/OVMF_VARS_4M.fd; do + [[ -f ${fw%%:*} && -f ${fw##*:} ]] && { FW_CODE=${fw%%:*}; FW_VARS=${fw##*:}; break; } +done +: "${FW_CODE:?no OVMF firmware found}" +[[ -r /dev/kvm && -w /dev/kvm ]] || { echo "vm-install: /dev/kvm is not usable" >&2; exit 1; } +GUEST_USER=omarchy; GUEST_PASSWORD=omarchy; GUEST_HOSTNAME=omarchy-vm; SSH_PORT=2422 +rm -rf "$W"; mkdir -p "$W/cidata" "$W/shots"; t0=$(date +%s); el() { echo $(( $(date +%s) - t0 )); } +ssh-keygen -q -t ed25519 -N '' -C omarchy-vm-build -f "$W/id_ed25519" +hash=$(openssl passwd -6 "$GUEST_PASSWORD") +disk_bytes=$((40*1024**3)); mib=$((1024**2)); boot_start=$mib; boot_size=$((2*1024**3)); main_start=$((boot_size+boot_start)); main_size=$((disk_bytes-main_start-mib)) +jq -n --arg h "$hash" --arg u "$GUEST_USER" '{root_enc_password:$h, users:[{enc_password:$h, groups:[], sudo:true, username:$u}]}' > "$W/cidata/user_credentials.json" +cat > "$W/cidata/user_configuration.json" </dev/null || { echo "bad json"; exit 1; } +echo "Omarchy Test" > "$W/cidata/user_full_name.txt"; echo "test@omarchy.org" > "$W/cidata/user_email_address.txt"; echo false > "$W/cidata/user_encrypt_installation.txt" +cp "$W/id_ed25519.pub" "$W/cidata/authorized_keys" +truncate -s 4M "$W/cidata.img"; mkfs.vfat -n CIDATA "$W/cidata.img" >/dev/null; mcopy -i "$W/cidata.img" "$W"/cidata/* ::/ +qemu-img create -f qcow2 "$W/disk.qcow2" 40G >/dev/null; cp "$FW_VARS" "$W/OVMF_VARS.4m.fd" +qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp 8 -m 8G \ + -drive if=pflash,format=raw,readonly=on,file="$FW_CODE" -drive if=pflash,format=raw,file="$W/OVMF_VARS.4m.fd" \ + -drive file="$W/disk.qcow2",format=qcow2,if=none,id=drive0 -device virtio-blk-pci,drive=drive0,bootindex=1 \ + -device virtio-vga -display none -usb -device usb-tablet \ + -netdev user,id=net0,hostfwd=tcp:127.0.0.1:$SSH_PORT-:22 -device virtio-net-pci,netdev=net0 \ + -qmp "unix:$W/qmp.sock,server,nowait" -serial "file:$W/serial.log" -pidfile "$W/qemu.pid" -daemonize \ + -drive "file=$ISO,media=cdrom,if=none,format=raw,id=cdrom0,readonly=on" -device ide-cd,drive=cdrom0,bootindex=2 \ + -drive "file=$W/cidata.img,format=raw,if=none,id=cidata" -device usb-storage,drive=cidata || exit 1 +qmp() { printf '{"execute":"qmp_capabilities"}\n%s\n' "$1" | socat - "unix-connect:$W/qmp.sock" >/dev/null 2>&1; } +shot() { qmp "{\"execute\":\"screendump\",\"arguments\":{\"filename\":\"$W/shots/$1.png\",\"format\":\"png\"}}"; } +sshg() { ssh -i "$W/id_ed25519" -p $SSH_PORT -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=3 -o LogLevel=ERROR $GUEST_USER@127.0.0.1 "$@"; } +echo "install started"; n=0 +while :; do + sshg true 2>/dev/null && { echo "ssh_up $(el)s"; break; } + kill -0 "$(cat "$W/qemu.pid")" 2>/dev/null || { echo "qemu exited at $(el)s"; exit 1; } + (( $(el) > 2400 )) && { shot timeout; echo "timeout"; exit 1; } + n=$((n+1)); (( n % 6 == 0 )) && { shot "$(printf 'p-%04d' "$(el)")"; sleep 1 + txt=$(tesseract "$W/shots/$(printf 'p-%04d' "$(el)")".png - 2>/dev/null || true) + grep -qi "Reboot Now" <<<"$txt" && { echo "reboot prompt $(el)s"; qmp '{"execute":"send-key","arguments":{"keys":[{"type":"qcode","data":"ret"}]}}'; } + grep -qi "installation stopped" <<<"$txt" && { echo "install stopped $(el)s"; exit 1; } + echo "... $(el)s"; } + sleep 10 +done +sshg 'timeout 180 systemctl is-system-running --wait; systemd-analyze; cat /etc/os-release | head -3; pacman -Q omarchy linux-omarchy 2>&1; cat ~/.local/share/omarchy/version 2>/dev/null' > "$W/first-boot.txt" 2>&1 +sshg 'sudo -n cat /var/log/omarchy-install-timing.json' > "$W/install-timing.json" 2>/dev/null +shot first-boot; echo "first_boot_checked $(el)s"; cat "$W/first-boot.txt" +# Power off cleanly, so the disk is consistent, and leave the three files vm-seal reads. +printf '%s\n' "$GUEST_PASSWORD" | sshg "sudo -S -p '' systemctl poweroff" 2>/dev/null || true +pid=$(cat "$W/qemu.pid"); for i in $(seq 1 120); do kill -0 "$pid" 2>/dev/null || break; sleep 1; done +kill -0 "$pid" 2>/dev/null && { echo "vm-install: the VM did not power off" >&2; exit 1; } +mv "$W/disk.qcow2" "$OUT/base.qcow2"; cp "$W/OVMF_VARS.4m.fd" "$W/id_ed25519" "$W/id_ed25519.pub" "$OUT/" +echo "installed: $OUT/base.qcow2 ($(du -sh "$OUT/base.qcow2" | cut -f1)) in $(el)s" diff --git a/test/vm-image/vm-seal b/test/vm-image/vm-seal new file mode 100755 index 0000000..683b27b --- /dev/null +++ b/test/vm-image/vm-seal @@ -0,0 +1,142 @@ +#!/bin/bash +# Turns an installed Omarchy disk (vm-install) into an image anyone can +# download and boot: every boot is its own machine, nothing of the build is +# left in it, and it boots straight into its kernel, so a boot takes seconds. +# +# vm-seal +# +# installed_dir holds base.qcow2, OVMF_VARS.4m.fd and id_ed25519. sealed_dir +# gets a standalone, zstd-compressed base.qcow2 and the UKI's vmlinuz, initrd +# and cmdline. It holds no key: each boot is handed one (see vm-boot). +# +# The image keeps the installer's user and password (GUEST_PASSWORD, default +# omarchy) for the desktop and sudo. SSH takes keys only. +set -euo pipefail +[[ $# -eq 2 ]] || { echo "Usage: vm-seal " >&2; exit 2; } +in=$(realpath "$1") out=$(realpath -m "$2") +pw=${GUEST_PASSWORD:-omarchy} +for fw in /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/OVMF/OVMF_CODE_4M.fd; do + [[ -f $fw ]] && { fw_code=$fw; break; } +done +: "${fw_code:?no OVMF firmware found}" + +state=$(mktemp -d /var/tmp/seal.XXXXXX) +cleanup() { + local status=$? pid + if [[ -f $state/qemu.pid ]]; then + pid=$(cat "$state/qemu.pid") + kill "$pid" 2>/dev/null || true + for _ in $(seq 1 50); do kill -0 "$pid" 2>/dev/null || break; sleep 0.1; done + fi + rm -rf "$state" + exit "$status" +} +trap cleanup EXIT +port=$(( 30000 + RANDOM % 5000 )) + +ssh_vm() { + ssh -i "$in/id_ed25519" -p "$port" -o BatchMode=yes -o IdentitiesOnly=yes \ + -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + -o ConnectTimeout=2 -o LogLevel=ERROR omarchy@127.0.0.1 "$@" +} +# Runs a script as root in the guest and fails if any line of it fails. The +# password goes to sudo on stdin, never into a command line. +root() { + printf '%s\n' "$pw" | ssh_vm "sudo -S -p '' bash -ec $(printf %q "trap 'echo \"vm-seal: failed in the guest at: \$BASH_COMMAND\" >&2' ERR +$1")" +} + +qemu-img create -qf qcow2 -b "$in/base.qcow2" -F qcow2 "$state/edit.qcow2" +cp "$in/OVMF_VARS.4m.fd" "$state/vars.fd" +qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm -smp 4 -m 4G \ + -drive if=pflash,format=raw,readonly=on,file="$fw_code" \ + -drive if=pflash,format=raw,file="$state/vars.fd" \ + -drive "file=$state/edit.qcow2,format=qcow2,if=virtio,discard=unmap" -display none \ + -netdev "user,id=n0,hostfwd=tcp:127.0.0.1:$port-:22" -device virtio-net-pci,netdev=n0 \ + -pidfile "$state/qemu.pid" -daemonize +for i in $(seq 1 150); do + ssh_vm true 2>/dev/null && break + (( i < 150 )) || { echo "vm-seal: no ssh on the installed disk" >&2; exit 1; } + sleep 2 +done +# Let first-boot work finish before taking it apart. +ssh_vm 'timeout 180 systemctl is-system-running --wait >/dev/null 2>&1 || true' + +mkdir -p "$out" +root 'cat /boot/EFI/Linux/omarchy_linux-omarchy.efi' >"$state/uki.efi" + +root ' + # The ISO writes autologin only for encrypted installs; a test has nobody at + # SDDM, and a desktop check that skips for want of a session reads as a pass. + printf "[Autologin]\nUser=omarchy\nSession=omarchy.desktop\n" >/etc/sddm.conf.d/autologin.conf + + # The image is public and its password is too, so SSH takes keys only. sshd + # keeps the first value it reads, hence a name that sorts first. + printf "PasswordAuthentication no\nKbdInteractiveAuthentication no\nAuthenticationMethods publickey\n" \ + >/etc/ssh/sshd_config.d/00-omarchy-vm.conf + ssh-keygen -A >/dev/null # sshd -T needs host keys to parse; they go below + sshd -T | grep -qix "passwordauthentication no" + sshd -T | grep -qix "authenticationmethods publickey" + + # Empty, not "uninitialized": that string marks a first boot, and a first boot + # applies unit presets, which on Arch disable everything not listed. Empty lets + # systemd take the VM SMBIOS UUID (qemu -uuid) as this boot machine ID. + # Host keys come back from sshdgenkeys.service before sshd starts. + : >/etc/machine-id + rm -f /var/lib/dbus/machine-id /etc/ssh/ssh_host_* + rm -f /home/omarchy/.ssh/authorized_keys /home/omarchy/.bash_history /root/.bash_history + + # The factory snapshot the installer took carries the same machine ID. + mkdir -p /run/seal-top + mount -o subvolid=5 "$(findmnt -no SOURCE / | sed "s/\[.*//")" /run/seal-top + if [ -f /run/seal-top/@factory/etc/machine-id ]; then + ro=$(btrfs property get -ts /run/seal-top/@factory ro) + [ "$ro" = ro=false ] || btrfs property set -ts /run/seal-top/@factory ro false + : >/run/seal-top/@factory/etc/machine-id + [ "$ro" = ro=false ] || btrfs property set -ts /run/seal-top/@factory ro true + fi + umount /run/seal-top + + # Stopping the unit saves a seed; with it stopped, shutdown saves none. + systemctl stop systemd-random-seed.service + rm -f /var/lib/systemd/random-seed /var/lib/systemd/credential.secret + + # Leases and the key NetworkManager derives stable addresses from. + systemctl stop NetworkManager.service + rm -f /var/lib/NetworkManager/*.lease /var/lib/NetworkManager/secret_key \ + /var/lib/NetworkManager/seen-bssids /var/lib/NetworkManager/timestamps \ + /var/lib/NetworkManager/NetworkManager.state + + # Vacuuming leaves the active journal. Send journald to /run, then the + # build logs on disk can go, and shutdown writes nothing back. + journalctl --relinquish-var + rm -rf /var/log/journal/* + + test ! -s /etc/machine-id + test -z "$(ls /etc/ssh/ssh_host_* /var/lib/NetworkManager/*.lease /var/log/journal/* 2>/dev/null)" + test ! -e /home/omarchy/.ssh/authorized_keys + test ! -e /var/lib/systemd/random-seed + + sync + # Hand freed blocks back to the disk image, so the copy skips them. + fstrim -av >/dev/null + (sleep 1; systemctl poweroff) >/dev/null 2>&1 &' + +# The key that let us in is gone, so the poweroff above was the last word. +pid=$(cat "$state/qemu.pid") +for _ in $(seq 1 120); do kill -0 "$pid" 2>/dev/null || break; sleep 1; done +if kill -0 "$pid" 2>/dev/null; then echo "vm-seal: the VM did not power off" >&2; exit 1; fi +rm -f "$state/qemu.pid" + +# Direct boot skips the firmware and Limine, which spend most of a boot reading +# and hashing the UKI. resume= points at the image's own swap, so drop it. +objcopy -O binary --only-section=.linux "$state/uki.efi" "$out/vmlinuz" +objcopy -O binary --only-section=.initrd "$state/uki.efi" "$out/initrd" +objcopy -O binary --only-section=.cmdline "$state/uki.efi" "$state/cmdline" +tr -d '\0' <"$state/cmdline" | tr ' ' '\n' | { grep -vE '^(resume|resume_offset)=|^$' || true; } | paste -sd' ' >"$out/cmdline" +[[ -s $out/vmlinuz && -s $out/initrd && -s $out/cmdline ]] || { echo "vm-seal: the UKI gave no kernel, initrd or cmdline" >&2; exit 1; } + +# zstd clusters: QEMU reads them as they are, so the download boots as it is. +qemu-img convert -c -O qcow2 -o compression_type=zstd -m 16 -W "$state/edit.qcow2" "$out/base.qcow2" +( cd "$out" && sha256sum base.qcow2 vmlinuz initrd cmdline >SHA256SUMS ) +echo "sealed: $out ($(du -sh "$out/base.qcow2" | cut -f1)); cmdline: $(cat "$out/cmdline")" diff --git a/test/vm-image/vm-verify b/test/vm-image/vm-verify new file mode 100755 index 0000000..dba443f --- /dev/null +++ b/test/vm-image/vm-verify @@ -0,0 +1,48 @@ +#!/bin/bash +# Boots a sealed image once, as a throwaway machine, and checks that it is +# what vm-seal promises: a desktop that comes up, nothing of the build left +# in it, and SSH that takes keys only. Exits non-zero on any failed check. +# +# vm-verify +set -euo pipefail +[[ $# -eq 1 ]] || { echo "Usage: vm-verify " >&2; exit 2; } +here=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) +base=$(realpath "$1") +( cd "$base" && sha256sum --quiet -c SHA256SUMS ) +uuid=$(cat /proc/sys/kernel/random/uuid) +export VM_UUID=$uuid SSH_PORT=$(( 20000 + RANDOM % 10000 )) + +VM_PW=${GUEST_PASSWORD:-omarchy} "$here/vm-boot" "$base" "WANT_ID=${uuid//-/} PW=${GUEST_PASSWORD:-omarchy} bash -s" <<'GUEST' +fail=0 +check() { # description, then a command that must succeed + local what=$1; shift + if "$@" >/dev/null 2>&1; then echo "ok $what"; else echo "FAIL $what"; fail=1; fi +} +root() { printf '%s\n' "$PW" | sudo -S -p '' "$@"; } +booted=$(( $(date +%s) - $(cut -d. -f1 /proc/uptime) - 5 )) +newer() { [ "$(root stat -c %Y "$1")" -ge "$booted" ]; } # written by this boot + +check "the system reaches running or degraded" \ + sh -c 's=$(timeout 120 systemctl is-system-running --wait); [ "$s" = running ] || [ "$s" = degraded ]' +check "no unit failed" sh -c '[ -z "$(systemctl --failed --no-legend)" ]' +check "a desktop session is logged in" sh -c 'for i in $(seq 1 60); do pgrep -x Hyprland && exit 0; sleep 0.5; done; exit 1' +check "the machine ID is the one this boot was given" [ "$(cat /etc/machine-id)" = "$WANT_ID" ] +check "the journal holds this machine only" [ "$(root ls /var/log/journal | tr '\n' ' ')" = "$WANT_ID " ] +check "SSH refuses passwords" sh -c "printf '%s\n' '$PW' | sudo -S -p '' sshd -T | grep -qix 'passwordauthentication no'" +check "SSH requires a key" sh -c "printf '%s\n' '$PW' | sudo -S -p '' sshd -T | grep -qix 'authenticationmethods publickey'" +# Asking with no method makes sshd list the ones it would take. +check "sshd offers a key as the only way in" \ + sh -c 'ssh -o PreferredAuthentications=none -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null omarchy@127.0.0.1 true 2>&1 | grep -qF "Permission denied (publickey)."' +check "authorized_keys holds one key, this boot's" [ "$(grep -c . ~/.ssh/authorized_keys)" = 1 ] +check "SSH host keys were made by this boot" newer /etc/ssh/ssh_host_ed25519_key +check "NetworkManager's key was made by this boot" newer /var/lib/NetworkManager/secret_key +check "one DHCP lease, this boot's" [ "$(root sh -c 'ls /var/lib/NetworkManager/*.lease | wc -l')" = 1 ] +check "no shell history" sh -c '! [ -e ~/.bash_history ]' +check "the package cache is empty" [ -z "$(ls /var/cache/pacman/pkg)" ] +root mkdir -p /run/top && root mount -o subvolid=5,ro "$(findmnt -no SOURCE / | sed 's/\[.*//')" /run/top +check "the factory snapshot has no machine ID" sh -c "! printf '%s\n' '$PW' | sudo -S -p '' test -s /run/top/@factory/etc/machine-id" +check "the factory snapshot has no SSH host keys" sh -c "[ -z \"\$(printf '%s\n' '$PW' | sudo -S -p '' sh -c 'ls /run/top/@factory/etc/ssh/ssh_host_* 2>/dev/null')\" ]" +check "no snapshots besides the current system" [ -z "$(root ls /.snapshots)" ] +echo "omarchy $(pacman -Q omarchy 2>/dev/null | cut -d' ' -f2), kernel $(uname -r), $(systemd-analyze | head -1)" +exit $fail +GUEST