Tuesday, December 27, 2022

debootstrap’ing a Recovery Partition

One of the nicer things about trying Fedora on my work laptop is that when it broke the boot loader, there was a functioning Recovery Mode.

My desktop relies on a particular driver for WiFi, and upgrading the kernel (e.g. from Ubuntu 22.04 to 22.10) requires fully reinstalling it.  But what if the kernel upgrades to a version that isn’t supported by the copy of the driver I happened to have on disk?  And I didn’t want to “just” (disassemble and move the PC to) plug in an Ethernet cable?

I used the Fedora live environment to make a little bit of room for an 8 GiB partition at the end of the disk (and a 2 GiB swap partition, as long as I was there), and then I ran debootstrap to fill it in.  This is about what surprised me doing that.

tl;dr: debootstrap is a lot more aggressively minimalist, more like Arch, than I would have expected.

Using debootstrap from a later Ubuntu (22.10) to install Debian Bullseye (2021-08) seemed to work fine.

The guide I was reading had an example sequence of how debootstrapping should work, suggesting I run dselect as my first thing in the chroot.  Well, the command wasn’t found, and when I installed it, I hated it.  The package list is grouped by several layers I don’t find terribly relevant, as I’m not a Debian release manager.

I went back to the familiar apt command to install dkms, build-essential, and git.  I cloned the driver from github.  Those were the things I knew I would need.  I would come back later to install the things I didn’t know I would need: linux-image-amd64, iw, rfkill, iwd, and (because I use Dvorak) console-setup.

I also tracked down and ran dpkg-reconfigure locales in the chroot, because perl was constantly complaining that there was no en_US.UTF-8 locale.  That was in the environment from outside the chroot, but no locales were generated inside.

I found the missing kernel right away; I couldn’t set up GRUB in Ubuntu to make use of Debian’s kernel, because it wasn’t there.

The next hurdle was that the system booted with a read-only root partition. It turns out that debootstrap leaves /etc/fstab blank.  I ran mount -o remount,rw / to fix it, then mounted the Ubuntu partition and copied the syntax from its fstab file.  I forgot about blkid; I got the correct UUID with lsblk -o NAME,UUID instead.  I don’t want to lock in a fixed physical architecture (i.e. the traditional /dev/sdb3 names.)

With that out of the way, I moved on to installing the driver, which is where iw and rfkill came in.  The installation only told me that iw was missing, but I suspected there would be more, so I searched the script and found everything it wanted from iw downward.  It was back to Ubuntu (working WiFi) to chroot in and install those.

With that, the driver built fine; it took another cycle through Ubuntu to read the Arch wiki, install iwd, set up a .network file for systemd, and reboot to Debian to supply the WPA2 password.  That last bit was a matter of running iwctl, typing station wlx984827[…] connect [SSID], and following the password prompt.  Success!  I had an IP address!

I went ahead and installed links and gpm, and then I was done.

(To boot Debian, I added a /boot/grub/custom.cfg file, sourced by Ubuntu’s /etc/grub.d/41_custom.  This must not be confused with /etc/grub.d/40_custom, which one would edit directly and thus cause conffile conflicts forever after.  The custom.cfg is a pair of menuentry blocks for the /vmlinuz and /vmlinuz.old symlinks in Debian’s root partition, with kernel options ro quiet splash.  debootstrap didn’t install a boot loader, so I left the partition that way.  The Debian GRUB can’t take over the boot process if there’s no Debian GRUB.  If I break Ubuntu’s GRUB, I can’t boot, but the main thing I’m worried about is breaking Ubuntu’s internet.)

No comments: