Raspberry Pi VM
Table of Contents
While attempting to automate building out of Reticulum nodes for PMesh. I checked to see if I could run the pi images in an emulator. Doing so would let me more easily clean-slate when testing my scripts.
Turns out this is doable using QEMU. Though it's not exactly as easy as starting up a vm in VirtManager.
1. Steps to build a VM
Download the image from here. Likely the image name will need to be updated in the script below:
#!/bin/sh set -e function unmount() { sudo umount boot } mkdir -p /tmp/pi-vm/{boot,root} cd /tmp/pi-vm IMG_FILE=2025-05-13-raspios-bookworm-arm64-lite.img IMG_BASE=$(basename $IMG_FILE .img) if [ ! -f $IMG_FILE ]; then curl -O https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2025-05-13/2025-05-13-raspios-bookworm-arm64-lite.img.xz unxz 2025-05-13-raspios-bookworm-arm64-lite.img.xz fi if [ ! -f ${IMG_BASE}.qcow2 ]; then trap unmount EXIT eval $(fdisk -l $IMG_FILE | awk '$2 ~ /^[0-9]+$/ {offset=$2*512; if ($6 == "c") {print "BOOT_OFFSET=" offset;} else {print "ROOT_OFFSET=" offset;}}') if [ -z "$BOOT_OFFSET" ]; then echo "Can't determine BOOT_OFFSET" exit 1 fi if [ -z "$ROOT_OFFSET" ]; then echo "Can't determine ROOT_OFFSET" exit 1 fi sudo mount $IMG_FILE -o offset=$BOOT_OFFSET boot cp boot/*.dtb . cp boot/kernel*.img . PASS=$(apg -m30 -n1) PASS_HASH=$(echo "$PASS" | mkpasswd -m yescrypt -s) echo "pi:${PASS_HASH}" | sudo tee boot/userconf echo "pi Password set to '${PASS}'" > info.txt sudo touch boot/ssh IMG_BASE=$(basename $IMG_FILE .img) qemu-img convert -f raw -O qcow2 $IMG_FILE ${IMG_BASE}.qcow2 qemu-img resize ${IMG_BASE}.qcow2 8G fi echo "qemu-system-aarch64 -m 1024 -M raspi3b \ -kernel kernel8.img \ -dtb bcm2710-rpi-3-b-plus.dtb \ -sd ${IMG_BASE}.qcow2 \ -snapshot \ -append 'root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4' \ -device usb-net,netdev=net0 \ -netdev user,id=net0,hostfwd=tcp::5555-:22" > run.sh chmod +x run.sh echo "run.sh created"