Assemble a bootable a linux image based on a kernel, an initramfs and a root filesystem.
- Using
syslinux
as a bootloader Busybox
as the small-footprint initramfs- An
Alpine
filesystem extracted from a docker image as our main filesystem
Bootable Disk Image
+----------------------+
| BOOTLOADER | +
+----------------------+ |
| LINUX KERNEL | |
+----------------------+ |
| INITRAMFS | |
+----------------------+ |
| ROOTFS | v
+----------------------+
usage: ./build-image.sh [output image] [kernel bzImage] [initramfs dir] [rootfs dir] [syslinux dir]
./build-image.sh my-linux.ext4 \
deps/linux/arch/x86/boot/bzImage \
deps/initramfs \
deps/alpine-root-dir \
deps/syslinux
qemu-system-x86_64 -drive file=my-linux.ext4,if=virtio,format=raw --nographic
In order to add network support to your VM you can add a TAP device to your host and use virtio-net in qemu. Note that mentions to eth0
need to be adapted to reflect your actual setup. If you plan to run multiple VMs you will need one TAP device for each.
On your host:
# create a TAP device
sudo ip tuntap add tap0 mode tap
# assign it an IP
sudo ip addr add 172.16.0.1/24 dev tap0
# bring it up
sudo ip link set tap0 up
# ensure your host can act as a router (forwarding packets)
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
# enable NAT/MASQUERADE for traffic out of your local interface
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# accept packets from existing connections
sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# forward traffic from your TAP device to your local interface
sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT
Then you can launch qemu with referring your new TAP device:
qemu-system-x86_64 -drive file=test.ext4,if=virtio,format=raw --nographic \
-netdev tap,id=net0,ifname=tap0,script=no,downscript=no \
-device virtio-net,netdev=net0
Finally, from your VM, setup the new interface (feel free to adapt it to better fit your needs):
ip addr add 172.16.0.2/24 dev eth0
ip link set eth0 up
ip route add default via 172.16.0.1 dev eth0
- Clone the Linux kernel source code:
git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux.git
. - Checkout the version you want to use:
git checkout v5.6.3
. - Run
make menuconfig
to have the nice TUI (or you can use my.config
file from the config directory). - Run
make -j$(nproc || echo -n 1)
to compile the kernel. - The compressed kernel image can be usually found in
linux/arch/x86/boot/bzImage
, this is the one to point the script to for the "kernel bzImage".
- Clone the Busybox repository:
git clone git://git.busybox.net/busybox
- Checkout the version you want to target (here the latest stable at time of writing):
git checkout 1_31_stable
- Run
make menuconfig
to have the nice TUI, and activate theSettings -> Build static binary (no shared libs)
option. This sets the flagCONFIG_STATIC=y
in the.config
file. - Run
make install -j$(nproc || echo -n 1)
to compile Busybox, and make it produce the nice root filesystem we are expecting under thebusybox/_install
folder.
TODO
TODO