Creating bootable Debian image with debootstrap
Kept at it and figured it out, relatively straight forward from here, but not just a matter of setting up /etc/fstab
, here is the rest:
not necessary but a good idea to clean things up
apt-get autoclean
set up /etc/fstab
- check with mount
to ensure you are on the right filesystem type
echo "/dev/sda1 / ext4 defaults,errors=remount-ro 0 1" > /etc/fstab
this will rebuild the initramfs and allow it to boot clean
update-initramfs -u -k all
Do that and the machine boots clean, tested in QEMU and then I am running it right now on hardware.
Automated Debian 9 setup without any systemd errors
This setup does not have any systemd errors or warnings, and I get the Internet connection and a shell at the end.
This setup is just not perfect as I'm not using the Debian kernel, errors when I tried explained in a later section. I then just tried a kernel I had lying around, with config based on Buildroot and it worked. The config is provided in this setup. Therefore, it is possible that some packages that rely on missing kernel configs will fail, although I haven't observed any errors so far.
An analogous setup worked perfectly with the Ubuntu kernel however: https://askubuntu.com/questions/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171 The Ubuntu kernel must have the missing configs compared to the Debian one. The Debian kernel failures can likely be fixed by compiling the Debian kernel with extra options like CONFIG_VIRTIO_BLK=y
as I've done for Ubuntu.
#!/usr/bin/env bash
set -eux
debootstrap_dir=debootstrap
root_filesystem=img.ext2.qcow2
sudo apt-get install \
debootstrap \
libguestfs-tools \
git \
qemu-system-x86 \
;
if [ ! -d "$debootstrap_dir" ]; then
# Create debootstrap directory.
# - linux-image-amd64: downloads the kernel image
sudo debootstrap \
--include linux-image-amd64 \
stretch \
"$debootstrap_dir" \
http://deb.debian.org/debian/ \
;
sudo rm -f "$root_filesystem"
fi
if [ ! -f "$root_filesystem" ]; then
# Set root password.
echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd
# Remount root filesystem as rw.
# Otherwise, systemd shows:
# [FAILED] Failed to start Create Volatile Files and Directories.
# and then this leads to further failures in the network setup.
cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF
# Network.
# We use enp0s3 because the kernel boot prints:
# 8139cp 0000:00:03.0 enp0s3: renamed from eth0
# This can also be observed with:
# ip link show
# Without this, systemd shows many network errors, the first of which is:
# [FAILED] Failed to start Network Time Synchronization.
cat << EOF | sudo tee "${debootstrap_dir}/etc/network/interfaces.d/00mytest"
auto lo
iface lo inet loopback
auto enp0s3
iface enp0s3 inet dhcp
EOF
# Generate image file from debootstrap directory.
# Leave 1Gb extra empty space in the image.
sudo virt-make-fs \
--format qcow2 \
--size +1G \
--type ext2 \
"$debootstrap_dir" \
"$root_filesystem" \
;
sudo chmod 666 "$root_filesystem"
fi
# linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"
linux_img=linux/arch/x86_64/boot/bzImage
if [ ! -f "$linux_img" ]; then
# Build the Linux kernel.
git clone --depth 1 --branch v4.18 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux
wget https://gist.githubusercontent.com/cirosantilli/6e2f4975c1929162a86be09f839874ca/raw/6d151d231a233408a6e1b541bf4a92fd55bf5338/.config
make olddefconfig
make -j`nproc`
cd -
fi
qemu-system-x86_64 \
-append 'console=ttyS0 root=/dev/sda' \
-drive "file=${root_filesystem},format=qcow2" \
-enable-kvm \
-serial mon:stdio \
-m 2G \
-kernel "$linux_img" \
-device rtl8139,netdev=net0 \
-netdev user,id=net0 \
;
GitHub upstream.
Now from the terminal, login with root
/ root
, and then check that the Internet works with the following commands:
printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n' | nc example.com 80
apt-get update
apt-get install hello
hello
We used nc
as explained at https://stackoverflow.com/questions/32341518/how-to-make-an-http-get-request-manually-with-netcat/52662497#52662497 because:
wget
andcurl
are not installed by defaultping
does not work from QEMU by default: How to ping from the QEMU guest to an external URL?
Tested on an Ubuntu 18.04 host.
What happens if I try to use the Debian kernel
TODO understand and fix. If I replace the Linux kernel compilation above with the Debian packaged Linux kernel:
linux_img="${debootstrap_dir}/boot/vmlinuz-"*
then boot fails with:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
and an empty list for:
List of all partitions:
so the disk is not being recognized at all. I've also tried to use the exact same kernel that the Debian ISO installer installs as done here but for Debian, and it fails in the same way, even though the Debian ISO install worked fine with the same QEMU options (it generates GRUB install in a disk with multiple partitions, the root one being ext4
).
Can't comment, but your "guide" worked wonders for making a Minimal Ubuntu 16 thumbdrive. The only things I changed were the debootstrap and I had to manually get networking working (networkd
).
My debootstrap line was:
#> sudo debootstrap --components=main,contrib,nonfree --variant=minbase \
--include=linux-generic,grub-pc --arch=i386 xenial /mnt