Build Your Own Linux Distribution: A Kernel Compilation and Virtualization

Markus Buchholz
4 min readJan 8, 2024

--

This article discusses the process of building a custom Linux distribution and provides a technical understanding with practical implementation. I will describe how to compile the Linux kernel in a Docker container, integrating a minimalistic environment using BusyBox. Finally, I will show how to boot our OS using QEMU.

The following diagram encapsulates the methodology of creating a custom Linux distribution by leveraging the modularity of BusyBox and the Linux Kernel.

by author

The Linux Kernel is the fundamental component that manages the system’s resources and facilitates communication between the hardware and software layers. It is responsible for critical aspects such as process management, memory handling, device I/O, and networking functionalities. In the context of a custom-built OS, the Linux Kernel can be fine-tuned during compilation to include only the necessary modules and drivers.

Adjacent to the Linux Kernel is BusyBox, which represents the user-space environment of the system. BusyBox is a collection of Unix utilities bundled into a single executable, providing a wide range of essential commands and tools for the system’s operation. These utilities cover basic shell functions, file manipulation, system administration, and networking tasks. Given its design for space-savings and modularity, BusyBox is particularly well-suited for embedded systems or minimalist Linux distributions. It offers the functionalities of a typical Linux command-line environment without the overhead of numerous standalone binaries.

The last component, QEMU, sits as a virtualization layer beneath the custom Linux OS, enabling the system to run on top of a host operating system. QEMU is a powerful emulator that can run an OS for one machine on a different machine — virtualizing the hardware resources. This means that the custom Linux OS does not directly interact with the physical hardware of the host system; instead, QEMU emulates the necessary hardware environment, allowing the custom OS to run as if it were on its intended hardware platform.

Build your Linux OS distribution.

Below is a diagram displaying the build environment. The Dockerfile, which installs all necessary libraries, tools and clones repositories, you can be found on my GitHub.

by author

Clone my repository and run the following commands (build and run Docker):

sudo docker build -t linux_os .

sudo docker run --privileged -it linux_os

Now, we can build the Linux kernel, which has been cloned to your Docker container.
Please run the command and save this configuration. You can optimize it if needed.

make menuconfig
# simply save

and build the Linux Kernel

make -j8

After build, the Kernel has the name bzImage

Run commands,

mkdir /boot-os

cp arch/x86/boot/bzImage /boot-os/

cd ../busybox

make menuconfig
# go to setting && under Build options choose: Build static binary (no shared libs) && save

Go to Settings and under Build options choose: Build static binary (no shared libs). Save.

Please execute the following commands:

make -j8

mkdir /boot-os/initramfs

make CONFIG_PREFIX=/boot-os/initramfs install

cd /boot-os/initramfs/

nano init

rm linuxrs

chmod +x init

find . | cpio -o -H newc > ../init.cpio

The setup of init file,

 #!/bin/sh
/bin/sh

Launch the other terminal and copy the necessary files from your Docker container to your host.

sudo docker ps -a
# 123456 is CONTAINER ID
sudo docker cp 6e62919338c3:/boot-os/bzImage .
sudo docker cp 6e62919338c3:/boot-os/init.cpio .

Now you can run your Linux OS running (install qemu):

#if you do not have qemu, install:

sudo apt install qemu-system-x86

# run Linux OS:

sudo qemu-system-x86_64 -kernel bzImage -initrd init.cpio

You can check your Linux Kernel version.

uname -r

Thanks for reading!

--

--