Over a year ago, I wrote about making ARM virtual machines. Times have changed a lot since then — the release of Apple M1 has dramatically changed the perception of ARM. No longer is ARM a niche platform for low-power gadgets like phones or tablets, but a viable desktop computing platform. Similarly, in the server space, Amazon Graviton and Ampere Altra have gained traction. My old blog post presented only a quick hack to get the ARM virtual machine to boot — by copying the kernel image. This leaves a lot to be desired. Somehow, despite this, it quickly became one of the popular posts on my blog. Today, we shall rectify that flaw and present a way to boot the latest kernel installed in the virtual machine using the Unified Extensible Firmware Interface (UEFI).
Again, like before, this tutorial will use Debian as an example, but the same methodology should work for other distributions. If you are looking for a simple chroot, you should instead follow the original post.
Step 1: Image Creation
Like last time, we will start by creating a raw disk image file. To do this, run:
$ sudo fallocate -l 8G /var/lib/libvirt/images/arm64-vm.img
Step 2: Run
virt-install to install Debian
With UEFI support, this process is very simple — you can simply run
virt-install and follow the on-screen instructions:
$ virt-install \ --name arm64-vm \ --arch aarch64 \ --machine virt \ --os-type Linux \ --os-variant debian11 \ --ram 2048 \ --vcpus 2 \ --import \ --disk /var/lib/libvirt/images/arm64-vm.img,bus=virtio \ --graphics none \ --network user,model=virtio \ --features acpi=off \ --boot uefi \ --location https://deb.debian.org/debian/dists/bullseye/main/installer-arm64/
Note that you might need to pass
--os-variant debian10 if
debian11 is not
The key flags here are
--boot uefi, which enables UEFI, and
which passes the path to the Debian installer to
virt-install. It will then
automatically download the installer and run it, without requiring you to
download the disk image. You can also pass
--vcpus to give the VM more cores,
--vcpus 4 for a quad core VM.
For 32-bit ARM, the
--location trick doesn’t work. Instead, you should
download the latest
armhf netinst image for Debian and use
$ wget https://cdimage.debian.org/debian-cd/current/armhf/iso-cd/debian-11.2.0-armhf-netinst.iso $ virt-install \ --name armhf-vm \ --arch armv7l \ --machine virt \ --os-type Linux \ --os-variant debian11 \ --ram 2048 \ --vcpus 2 \ --import \ --disk /var/lib/libvirt/images/armhf-vm.img,bus=virtio \ --graphics none \ --network user,model=virtio \ --features acpi=off \ --boot uefi \ --cdrom debian-11.2.0-armhf-netinst.iso
Step 3: Use
Simply follow the on-screen instructions to select your language and country. If everything goes well, it should automatically configure the network. If not, you can follow the instructions on the screen to set up networking, but that is outside the scope of this quick tutorial.
Assuming network autoconfiguration worked, you should end up on this screen:
[ (1*installer) 2 shell 3 shell 4- log ][ Mar 19 7:19 ] ┌─────────────────────┤ [!] Configure the network ├─────────────────────┐ │ │ │ Please enter the hostname for this system. │ │ │ │ The hostname is a single word that identifies your system to the │ │ network. If you don't know what your hostname should be, consult your │ │ network administrator. If you are setting up your own home network, │ │ you can make something up here. │ │ │ │ Hostname: │ │ │ │ debian_______________________________________________________________ │ │ │ │ <Go Back> <Continue> │ │ │ └───────────────────────────────────────────────────────────────────────┘ <Tab> moves; <Space> selects; <Enter> activates buttons
Continue to follow on-screen instructions. When prompted to select a Debian
archive mirror, you are highly recommended to select
manually. Debian installer will populate it with
deb.debian.org, which is
usually the fastest option anywhere in the world (it uses a CDN).
The installer will download some components. Eventually, it will prompt you to set up users and passwords, but simply follow on-screen instructions. Then, wait for the installer to load additional components.
Once this is done, you will be prompted to partition your system:
[ (1*installer) 2 shell 3 shell 4- log ][ Mar 19 7:27 ] ┌────────────────────────┤ [!!] Partition disks ├─────────────────────────┐ │ │ │ The installer can guide you through partitioning a disk (using │ │ different standard schemes) or, if you prefer, you can do it │ │ manually. With guided partitioning you will still have a chance later │ │ to review and customise the results. │ │ │ │ If you choose guided partitioning for an entire disk, you will next │ │ be asked which disk should be used. │ │ │ │ Partitioning method: │ │ │ │ Guided - use entire disk │ │ Guided - use entire disk and set up LVM │ │ Guided - use entire disk and set up encrypted LVM │ │ Manual │ │ │ │ <Go Back> │ │ │ └─────────────────────────────────────────────────────────────────────────┘ <Tab> moves; <Space> selects; <Enter> activates buttons
Guided - use entire disk and then
All files in one partition is
sufficient for our purposes. The installer will do something like:
[ (1*installer) 2 shell 3 shell 4- log ][ Mar 19 7:28 ] ┌────────────────────────┤ [!!] Partition disks ├─────────────────────────┐ │ │ │ This is an overview of your currently configured partitions and mount │ │ points. Select a partition to modify its settings (file system, mount │ │ point, etc.), a free space to create partitions, or a device to │ │ initialize its partition table. │ │ │ │ Virtual disk 1 (vda) - 8.6 GB Virtio Block Device - │ │ > 1.0 MB FREE SPACE ▒ │ │ > #1 536.9 MB B f ESP ▒ │ │ > #2 7.0 GB f ext4 / ▒ │ │ > #3 1.0 GB f swap swap ▒ │ │ > 1.0 MB FREE SPACE ▒ │ │ ▒ │ │ Undo changes to partitions 0 │ │ Finish partitioning and write changes to disk . │ │ │ │ <Go Back> │ │ │ └─────────────────────────────────────────────────────────────────────────┘ <F1> for help; <Tab> moves; <Space> selects; <Enter> activates buttons
This is fine, select
Finish partitioning and write changes to disk, and the
process should continue. When prompted to write the changes to disk, select
You can also choose to manually partition, but keep in mind you will need an EFI system partition (ESP), and the minimum size for that is 100 MiB.
Either way, the installer will do its work. Once the base system is installed, it’ll prompt you to install additional software:
[ (1*installer) 2 shell 3 shell 4- log ][ Mar 19 7:56 ] ┌───────────────────────┤ [!] Software selection ├────────────────────────┐ │ │ │ At the moment, only the core of the system is installed. To tune the │ │ system to your needs, you can choose to install one or more of the │ │ following predefined collections of software. │ │ │ │ Choose software to install: │ │ │ │ [ ] ... KDE Plasma - │ │ [ ] ... Cinnamon ▒ │ │ [ ] ... MATE ▒ │ │ [ ] ... LXDE ▒ │ │ [ ] ... LXQt ▒ │ │ [ ] web server ▒ │ │ [*] SSH server 0 │ │ [ ] standard system utilities . │ │ │ │ <Continue> │ │ │ └─────────────────────────────────────────────────────────────────────────┘ <Tab> moves; <Space> selects; <Enter> activates buttons
Since everything can be installed later, you don’t have to install anything. However, the SSH server is rather useful, especially since SSHing into the VM offers a massively better experience than typing into the console.
Once the system finishes installing whatever additional software, it will
grub, the bootloader, which will be loaded by the UEFI firmware to
boot the system. At this point, the installation will be complete:
[ (1*installer) 2 shell 3 shell 4- log ][ Mar 19 8:01 ] ┌───────────────────┤ [!!] Finish the installation ├────────────────────┐ │ │ ┌│ Installation complete │ ││ Installation is complete, so it is time to boot into your new system. │ ││ Make sure to remove the installation media, so that you boot into the │ ││ new system rather than restarting the installation. │ ││ │ ││ <Go Back> <Continue> │ └│ │ └───────────────────────────────────────────────────────────────────────┘ <Tab> moves; <Space> selects; <Enter> activates buttons
Continue, and the system will reboot.
virt-install will take
care of removing the installation media. After rebooting, you should be in a
serial console. Your VM is now ready!
To leave the console, press Ctrl+]. To return, run
console arm64-vm (or whatever name you passed to
--name argument of
virt-install will use user-mode networking. This is the easiest
form of networking to set up, but the internal IPs generated are not actually
accessible from the outside, including your host machine. You have two options:
- You could reconfigure the VM to use a virtual NAT network, which would allow
access from the host. The easiest way to do this is to open the VM in
virt-managerand change the network source.
- You could reconfigure the VM to use a bridged network, which would allow it to show up on your local network. This is out-of-scope for this quick guide.
- You can set up port forwarding, e.g.
virsh qemu-monitor-command --hmp arm64-vm 'hostfwd_add ::2222-:22'. This will forward
22in the VM. You can then run
ssh -p 2222 localhostto access the VM.
Congratulations! You now have an ARM virtual machine. Unlike last time, upgrading the kernel should be completely seamless. Enjoy!