Debian rootfs for Arm using Debootstrap and QEMU

In this article you will see how to create a minimal Debian image for your embedded device from your x86 host system using Debootstrap. Debootstrap is a command line tool for creating Debian distribution of your choice for any architecture. You can create your minimal Debian image for both Arm and x86 systems. Remember at the end of this process will only have the rootfs and not the kernel. We can use this rootfs for cross-compiling our embedded applications using our host development computer’s computing power instead of building on the target device.

In this example we will be creating a Debian Buster image for arm architecture (armhf) from our x86 64 bit host operating system xUbuntu 22.04.

Required packages

First, we need to install prerequisities to create our Debian rootfs. Run the following commands to install our dependencies:

apt install qemu-user-static debootstrap

First stage

Now we can proceed with debootstrap. First we create a folder to create the rootfs in:

sudo mkdir /opt/sysroots/debian-buster-armhf

Run the following command to start first stage:

debootstrap --arch=armhf --foreign buster /opt/sysroots/debian-buster-armhf

If you want another Debian version, simply change buster with the version you want (i.e. bookworm). Run the above command and wait for it to download all required packages. This may take some time.

Screenshot of Debootstrap installing the first stage packages.
Screenshot of Debootstrap installing the first stage packages.

Second stage

Once the first stage is finished, we can go ahead and copy qemu-arm-static to our rootfs and start the second stage.

cp /usr/bin/qemu-arm-static /opt/sysroots/debian-buster-armhf/usr/bin

Now we chroot into our rootfs to start the second stage. For this you need to run:

chroot /opt/sysroots/debian-buster-armhf /usr/bin/qemu-arm-static /bin/sh -i

Note: If you have any additional commands in your .bashrc that is not supported by /bin/sh you can replace /bin/sh with /bin/bash int the command above so you don’t see erroneous shell prompt everytime you enter a command.

If you’ve managed to chroot into your rootfs, it’s now time to start the second stage. Run:

/debootstrap/debootstrap --second-stage

Second stage also might take some time. Once it’s finished we can exit and chroot back in so non-existing username ‘I have no name!’ will disappear and we will chroot as root.

Screenshot from our rootfs' shell. You can see that architecture is armv7l even though we are running it on our x86 host machine.
Screenshot from our rootfs’ shell. You can see that architecture is armv7l even though we are running it on our x86 host machine.

As you can see after we chroot again, everything looks fine and your Debian Booster rootfs is ready for cross development. For more details about the Debootstrap visit Debian’s official document.