SDL fallback, partition fix, lz4 remote streaming, delay-oobe-run

SDL display:
- try SDL, auto-fallback to headless if it fails (no crash)
- SDL_VIDEODRIVER=x11 to avoid wayland socket path issues
- suppress XDG_RUNTIME_DIR warnings

Disk copy:
- zap-all before writing to clear old partition tables
- delete recovery partition (4) before resizing partition 3
- use parted resizepart (preserves partition GUID for BCD)
- remote: nix-shell for sgdisk/parted/ntfsresize on target
- remote: lz4 compression for faster streaming
- remote: pv progress bar with disk size
- -y/--yes flag to skip confirmation prompt

Generalize:
- delay-oobe-run=true defers OOBE + activation to real hardware
- clean cached Autounattend from Windows\Panther before sysprep
- taskkill sysprep.exe on first login (CopyProfile artifact)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Git Sagar 2026-05-24 11:01:39 -03:00
parent ebfb10b3b3
commit 89a0673f54
4 changed files with 79 additions and 37 deletions

View file

@ -126,6 +126,7 @@
GENERALIZE=""
TO_DISK=""
TO_REMOTE_DISK=""
YES=false
OUT_LINK="./result"
while [[ ''${#} -gt 0 ]]; do
@ -134,6 +135,7 @@
--generalize) GENERALIZE="$2"; shift 2 ;;
--to-disk) TO_DISK="$2"; shift 2 ;;
--to-remote-disk) TO_REMOTE_DISK="$2"; shift 2 ;;
-y|--yes) YES=true; shift ;;
--out-link) OUT_LINK="$2"; shift 2 ;;
--help|-h) usage ;;
*) echo "Unknown option: $1"; usage ;;
@ -212,17 +214,24 @@
echo "Target: $TO_DISK ($DISK_SIZE_GB GB)"
echo ""
echo "WARNING: This will DESTROY all data on $TO_DISK"
read -rp "Continue? [y/N] " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { echo "Aborted."; exit 0; }
if [[ "$YES" != "true" ]]; then
read -rp "Continue? [y/N] " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { echo "Aborted."; exit 0; }
fi
echo ""
echo "[1/4] Writing image to disk..."
echo "[1/5] Wiping partition table..."
${pkgs.gptfdisk}/bin/sgdisk --zap-all "$TO_DISK"
echo "[2/5] Writing image to disk..."
${pkgs.qemu}/bin/qemu-img convert -p -S 4k -f qcow2 -O raw "$IMAGE_FILE" "$TO_DISK"
echo "[2/4] Fixing GPT backup header..."
echo "[3/5] Fixing GPT backup header..."
${pkgs.gptfdisk}/bin/sgdisk -e "$TO_DISK"
# delete recovery partition if present, then resize Windows partition
${pkgs.gptfdisk}/bin/sgdisk -d 4 "$TO_DISK" 2>/dev/null || true
echo "[3/4] Expanding Windows partition (partition 3) to fill disk..."
echo "[4/5] Expanding Windows partition (partition 3)..."
${pkgs.parted}/bin/parted -s "$TO_DISK" resizepart 3 100%
if [[ "$TO_DISK" == *nvme* ]] || [[ "$TO_DISK" == *mmcblk* ]]; then
@ -231,7 +240,7 @@
WIN_PART="''${TO_DISK}3"
fi
echo "[4/4] Expanding NTFS filesystem on $WIN_PART..."
echo "[5/5] Expanding NTFS filesystem on $WIN_PART..."
${pkgs.ntfs3g}/bin/ntfsresize --force --no-action "$WIN_PART"
echo "y" | ${pkgs.ntfs3g}/bin/ntfsresize --force "$WIN_PART"
@ -252,19 +261,28 @@
echo "Disk: $REMOTE_DISK"
echo ""
echo "WARNING: This will DESTROY all data on $REMOTE_HOST:$REMOTE_DISK"
read -rp "Continue? [y/N] " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { echo "Aborted."; exit 0; }
if [[ "$YES" != "true" ]]; then
read -rp "Continue? [y/N] " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { echo "Aborted."; exit 0; }
fi
echo ""
echo "[1/4] Streaming image to remote disk..."
${pkgs.qemu}/bin/qemu-img convert -f qcow2 -O raw "$IMAGE_FILE" /dev/stdout \
| ssh "$REMOTE_HOST" "dd of=$REMOTE_DISK bs=4M status=progress oflag=direct"
echo "[1/5] Wiping partition table..."
ssh "$REMOTE_HOST" "sgdisk --zap-all $REMOTE_DISK"
echo "[2/4] Fixing GPT backup header..."
ssh "$REMOTE_HOST" "sgdisk -e $REMOTE_DISK"
echo "[3/4] Expanding Windows partition (partition 3) to fill disk..."
ssh "$REMOTE_HOST" "parted -s $REMOTE_DISK resizepart 3 100%"
echo "[2/5] Streaming image to remote disk..."
NBD_SOCK="/tmp/vmix-nbd-$$.sock"
${pkgs.qemu}/bin/qemu-nbd --read-only -f qcow2 -k "$NBD_SOCK" "$IMAGE_FILE" &
NBD_PID=$!
trap "kill $NBD_PID 2>/dev/null; rm -f $NBD_SOCK" EXIT
while [ ! -S "$NBD_SOCK" ]; do sleep 0.1; done
DISK_SIZE=$(${pkgs.libnbd}/bin/nbdinfo --size "nbd+unix:///?socket=$NBD_SOCK")
${pkgs.libnbd}/bin/nbdcopy --request-size=4194304 "nbd+unix:///?socket=$NBD_SOCK" - \
| ${pkgs.pv}/bin/pv -s "$DISK_SIZE" \
| ${pkgs.lib.getBin pkgs.lz4}/bin/lz4 -1 - \
| ssh "$REMOTE_HOST" "nix-shell -p lz4 --run 'lz4 -d - - | dd of=$REMOTE_DISK bs=4M iflag=fullblock oflag=direct conv=sparse'"
kill $NBD_PID 2>/dev/null || true
rm -f "$NBD_SOCK"
if [[ "$REMOTE_DISK" == *nvme* ]] || [[ "$REMOTE_DISK" == *mmcblk* ]]; then
REMOTE_WIN_PART="''${REMOTE_DISK}p3"
@ -272,8 +290,14 @@
REMOTE_WIN_PART="''${REMOTE_DISK}3"
fi
echo "[4/4] Expanding NTFS filesystem on $REMOTE_WIN_PART..."
ssh "$REMOTE_HOST" "echo y | ntfsresize --force $REMOTE_WIN_PART"
echo "[3/5] Fixing GPT backup header..."
ssh "$REMOTE_HOST" "nix-shell -p gptfdisk --run 'sgdisk -e $REMOTE_DISK && sgdisk -d 4 $REMOTE_DISK 2>/dev/null || true'"
echo "[4/5] Expanding Windows partition (partition 3)..."
ssh "$REMOTE_HOST" "nix-shell -p parted --run 'parted -s $REMOTE_DISK resizepart 3 100%'"
echo "[5/5] Expanding NTFS filesystem on $REMOTE_WIN_PART..."
ssh "$REMOTE_HOST" "nix-shell -p ntfs3g --run 'echo y | ntfsresize --force $REMOTE_WIN_PART'"
echo ""
echo "Done. $REMOTE_HOST:$REMOTE_DISK is ready to boot."