Create a Debian VM on MacOS Apple Silicon with Qemu

Couple of things before everything. Firstly, make sure your machine has an ARM CPU. Secondly, open a terminal application such as Terminal.app or iTerm2 (boooo!), this process isn't tested with VSCode's terminal. Lastly, go into a directory where you would like to store the vm disk. Let's get started.

Downloading stuff

Get qemu. For example if you use homebrew

$ brew install qemu

Check qemu is installed

$ which qemu-system-aarch64
/opt/homebrew/bin/qemu-system-aarch64

Now download a debian installation image, here we use the netinst image for Debian 12 (bookworm)

$ wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-12.5.0-arm64-netinst.iso

Creating the files

And create a disk image for qemu to use. Here we choose the qcow2 format with 64G space. It is a "on-demand" format where the disk file is small when mostly empty. Adjust it for your potential need.

$ qemu-img create -f qcow2 disk.img 64G

Now comes the tricky part, there appears to be a problem with the UEFI firmware, most of the complexity of this guide is to address that. Find the firmware for arm64 (this is put there by qemu, but it's not being used by default)

$ find /opt/homebrew -name 'edk2-aarch64-code.fd'
/opt/homebrew/Cellar/qemu/8.2.2/share/qemu/edk2-aarch64-code.fd

Copy it to the local directory for simplicity (or not, then your next command will replace the edk2-aarch64-code.fd with the full path)

$ cp /opt/homebrew/Cellar/qemu/8.2.2/share/qemu/edk2-aarch64-code.fd ./

Also we need a drive for varstore

$ dd if=/dev/zero conv=sync bs=1m count=64 of=ovmf_vars.fd

Installing Debian

Fire up qemu to install a debian system on disk.img

$ qemu-system-aarch64 -M virt \
                      -accel hvf \
                      -smp 2 -m 8G -cpu host \
                      -boot d -cdrom debian-12.5.0-arm64-netinst.iso \
                      -drive "format=raw,file=edk2-aarch64-code.fd,if=pflash,readonly=on" \
                      -drive "format=raw,file=ovmf_vars.fd,if=pflash" \
                      -hda disk.img \
                      -device e1000,netdev=usernet \
                      -netdev user,id=usernet,hostfwd=tcp:0.0.0.0:10000-:22 \
                      -nographic

Notable things:

If all goes wrong you'll realize you cannot use ctrl-c to exit the program. You should do the following instead: ctrl-a c. This will give you something that looks like this:

QEMU 8.2.2 monitor - type 'help' for more information
(qemu)

You can enter quit to exit the qemu process from here.

The shell will look a bit strange afterwards because qemu changed the mode of tty. To get it back you just run reset in your command line.

There are a lot of resources on how to install a debian from the installer. I'll skip that here. Just make sure to install the ssh-server at the end.

Booting into the VM

After successfully install the vm, qemu will reboot into the newly installed debian. In the future if you wish to start the vm you can run

$ qemu-system-aarch64 -M virt \
                      -accel hvf \
                      -smp 2 -m 8G -cpu host \
                      -drive "format=raw,file=edk2-aarch64-code.fd,if=pflash,readonly=on" \
                      -drive "format=raw,file=ovmf_vars.fd,if=pflash" \
                      -hda disk.img \
                      -device e1000,netdev=usernet \
                      -netdev user,id=usernet,hostfwd=tcp:0.0.0.0:10000-:22 \
                      -nographic

The -netdev user,id=usernet,hostfwd=tcp:0.0.0.0:10000-:22 option forwards the host's 10000 tcp port to VM's 22 tcp port, so you can do this to connect to it through ssh

$ ssh -p 10000 myuser@localhost

References

https://unix.stackexchange.com/questions/682733/cannot-boot-aarch64-alpine-linux-on-mac-os-using-qemu-6-2-0 https://ricardobalk.nl/blog/linux/debian-on-macos