summaryrefslogtreecommitdiffstats
path: root/examples/twb/debian-11-minimal.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/twb/debian-11-minimal.py')
-rw-r--r--examples/twb/debian-11-minimal.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/examples/twb/debian-11-minimal.py b/examples/twb/debian-11-minimal.py
new file mode 100644
index 0000000..fac7b9b
--- /dev/null
+++ b/examples/twb/debian-11-minimal.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+import argparse
+import pathlib
+import subprocess
+import tempfile
+import pathlib
+
+__author__ = "Trent W. Buck"
+__copyright__ = "Copyright © 2020 Trent W. Buck"
+__license__ = "expat"
+
+__doc__ = """ build the simplest Debian Live image that can boot
+
+This uses mmdebstrap to do the heavy lifting;
+it can run entirely without root privileges.
+It emits a USB key disk image that contains a bootable EFI ESP,
+which in turn includes a bootloader (refind), kernel, ramdisk, and filesystem.squashfs.
+
+NOTE: this is the simplest config possible.
+ It lacks CRITICAL SECURITY AND DATA LOSS packages, such as amd64-microcode and smartd.
+"""
+
+parser = argparse.ArgumentParser(description=__doc__)
+parser.add_argument(
+ "output_file", nargs="?", default=pathlib.Path("filesystem.img"), type=pathlib.Path
+)
+args = parser.parse_args()
+
+
+filesystem_img_size = "256M" # big enough to include filesystem.squashfs + about 64M of bootloader, kernel, and ramdisk.
+esp_offset = 1024 * 1024 # 1MiB
+esp_label = "UEFI-ESP" # max 8 bytes for FAT32
+live_media_path = "debian-live"
+
+with tempfile.TemporaryDirectory(prefix="debian-live-bullseye-amd64-minimal.") as td:
+ td = pathlib.Path(td)
+ subprocess.check_call(
+ [
+ "mmdebstrap",
+ "--mode=unshare",
+ "--variant=apt",
+ '--aptopt=Acquire::http::Proxy "http://apt-cacher-ng.cyber.com.au:3142"',
+ '--aptopt=Acquire::https::Proxy "DIRECT"',
+ "--dpkgopt=force-unsafe-io",
+ "--include=linux-image-amd64 init initramfs-tools live-boot netbase",
+ "--include=dbus", # https://bugs.debian.org/814758
+ "--include=live-config iproute2 keyboard-configuration locales sudo user-setup",
+ "--include=ifupdown isc-dhcp-client", # live-config doesn't support systemd-networkd yet.
+ # Do the **BARE MINIMUM** to make a USB key that can boot on X86_64 UEFI.
+ # We use mtools so we do not ever need root privileges.
+ # We can't use mkfs.vfat, as that needs kpartx or losetup (i.e. root).
+ # We can't use mkfs.udf, as that needs mount (i.e. root).
+ # We can't use "refind-install --usedefault" as that runs mount(8) (i.e. root).
+ # We don't use genisoimage because
+ # 1) ISO9660 must die;
+ # 2) incomplete UDF 1.5+ support;
+ # 3) resulting filesystem can't be tweaked after flashing (e.g. debian-live/site.dir/etc/systemd/network/up.network).
+ #
+ # We use refind because 1) I hate grub; and 2) I like refind.
+ # If you want aarch64 or ia32 you need to install their BOOTxxx.EFI files.
+ # If you want kernel+initrd on something other than FAT, you need refind/drivers_xxx/xxx_xxx.EFI.
+ #
+ # FIXME: with qemu in UEFI mode (OVMF), I get dumped into startup.nsh (UEFI REPL).
+ # From there, I can manually type in "FS0:\EFI\BOOT\BOOTX64.EFI" to start refind, tho.
+ # So WTF is its problem? Does it not support fallback bootloader?
+ "--include=refind parted mtools",
+ "--essential-hook=echo refind refind/install_to_esp boolean false | chroot $1 debconf-set-selections",
+ "--customize-hook=echo refind refind/install_to_esp boolean true | chroot $1 debconf-set-selections",
+ "--customize-hook=chroot $1 mkdir -p /boot/USB /boot/EFI/BOOT",
+ "--customize-hook=chroot $1 cp /usr/share/refind/refind/refind_x64.efi /boot/EFI/BOOT/BOOTX64.EFI",
+ f"--customize-hook=chroot $1 truncate --size={filesystem_img_size} /boot/USB/filesystem.img",
+ f"--customize-hook=chroot $1 parted --script --align=optimal /boot/USB/filesystem.img mklabel gpt mkpart {esp_label} {esp_offset}b 100% set 1 esp on",
+ f"--customize-hook=chroot $1 mformat -i /boot/USB/filesystem.img@@{esp_offset} -F -v {esp_label}",
+ f"--customize-hook=chroot $1 mmd -i /boot/USB/filesystem.img@@{esp_offset} ::{live_media_path}",
+ f"""--customize-hook=echo '"Boot with default options" "boot=live live-media-path={live_media_path}"' >$1/boot/refind_linux.conf""",
+ # NOTE: find sidesteps the "glob expands before chroot applies" problem.
+ f"""--customize-hook=chroot $1 find -O3 /boot/ -xdev -mindepth 1 -maxdepth 1 -regextype posix-egrep -iregex '.*/(EFI|refind_linux.conf|vmlinuz.*|initrd.img.*)' -exec mcopy -vsbpm -i /boot/USB/filesystem.img@@{esp_offset} {{}} :: ';'""",
+ # FIXME: copy-out doesn't handle sparseness, so is REALLY slow (about 50 seconds).
+ # Therefore instead leave it in the squashfs, and extract it later.
+ # f'--customize-hook=copy-out /boot/USB/filesystem.img /tmp/',
+ # f'--customize-hook=chroot $1 rm /boot/USB/filesystem.img',
+ "bullseye",
+ td / "filesystem.squashfs",
+ ]
+ )
+
+ with args.output_file.open("wb") as f:
+ subprocess.check_call(
+ ["rdsquashfs", "--cat=boot/USB/filesystem.img", td / "filesystem.squashfs"],
+ stdout=f,
+ )
+ subprocess.check_call(
+ [
+ "mcopy",
+ "-i",
+ f"{args.output_file}@@{esp_offset}",
+ td / "filesystem.squashfs",
+ f"::{live_media_path}/filesystem.squashfs",
+ ]
+ )