@ -19,197 +19,194 @@ which in turn includes a bootloader (refind), kernel, ramdisk, and filesystem.sq
"""
"""
parser = argparse . ArgumentParser ( description = __doc__ )
parser = argparse . ArgumentParser ( description = __doc__ )
parser . add_argument ( ' output_file ' , nargs = ' ? ' , default = pathlib . Path ( ' filesystem.img ' ) , type = pathlib . Path )
parser . add_argument (
parser . add_argument ( ' --timezone ' , default = ' Australia/Melbourne ' , type = lambda s : s . split ( ' / ' ) , help = ' NOTE: MUST be " Area/Zone " not e.g. " UTC " , for now ' )
" output_file " , nargs = " ? " , default = pathlib . Path ( " filesystem.img " ) , type = pathlib . Path
parser . add_argument ( ' --locale ' , default = ' en_AU.UTF-8 ' , help = ' NOTE: MUST end in " .UTF-8 " , for now ' )
)
parser . add_argument (
" --timezone " ,
default = " Australia/Melbourne " ,
type = lambda s : s . split ( " / " ) ,
help = ' NOTE: MUST be " Area/Zone " not e.g. " UTC " , for now ' ,
)
parser . add_argument (
" --locale " , default = " en_AU.UTF-8 " , help = ' NOTE: MUST end in " .UTF-8 " , for now '
)
args = parser . parse_args ( )
args = parser . parse_args ( )
filesystem_img_size = ' 512M ' # big enough to include filesystem.squashfs + about 64M of bootloader, kernel, and ramdisk.
filesystem_img_size = " 512M " # big enough to include filesystem.squashfs + about 64M of bootloader, kernel, and ramdisk.
esp_offset = 1024 * 1024 # 1MiB
esp_offset = 1024 * 1024 # 1MiB
esp_label = ' UEFI-ESP ' # max 8 bytes for FAT32
esp_label = " UEFI-ESP " # max 8 bytes for FAT32
live_media_path = ' debian-live '
live_media_path = " debian-live "
with tempfile . TemporaryDirectory ( prefix = ' debian-sid-zfs. ' ) as td :
with tempfile . TemporaryDirectory ( prefix = " debian-sid-zfs. " ) as td :
td = pathlib . Path ( td )
td = pathlib . Path ( td )
subprocess . check_call (
subprocess . check_call (
[ ' mmdebstrap ' ,
[
' --mode=unshare ' ,
" mmdebstrap " ,
' --variant=apt ' ,
" --mode=unshare " ,
' --aptopt=Acquire::http::Proxy " http://apt-cacher-ng.cyber.com.au:3142 " ' ,
" --variant=apt " ,
' --aptopt=Acquire::https::Proxy " DIRECT " ' ,
' --aptopt=Acquire::http::Proxy " http://apt-cacher-ng.cyber.com.au:3142 " ' ,
' --dpkgopt=force-unsafe-io ' ,
' --aptopt=Acquire::https::Proxy " DIRECT " ' ,
' --components=main contrib non-free ' , # needed for CPU security patches
" --dpkgopt=force-unsafe-io " ,
" --components=main contrib non-free " , # needed for CPU security patches
' --include=init initramfs-tools xz-utils live-boot netbase ' ,
" --include=init initramfs-tools xz-utils live-boot netbase " ,
' --include=dbus ' , # https://bugs.debian.org/814758
" --include=dbus " , # https://bugs.debian.org/814758
' --include=linux-image-amd64 firmware-linux ' ,
" --include=linux-image-amd64 firmware-linux " ,
# Have ZFS 2.0 support.
# Have ZFS 2.0 support.
" --include=zfs-dkms zfsutils-linux zfs-zed build-essential linux-headers-amd64 " , # ZFS 2 support
' --include=zfs-dkms zfsutils-linux zfs-zed build-essential linux-headers-amd64 ' , # ZFS 2 support
# Make the initrd a little smaller (41MB -> 20MB), at the expensive of significantly slower image build time.
" --include=zstd " ,
# Make the initrd a little smaller (41MB -> 20MB), at the expensive of significantly slower image build time.
" --essential-hook=mkdir -p $1/etc/initramfs-tools/conf.d " ,
' --include=zstd ' ,
" --essential-hook=>$1/etc/initramfs-tools/conf.d/zstd echo COMPRESS=zstd " ,
' --essential-hook=mkdir -p $1/etc/initramfs-tools/conf.d ' ,
# Be the equivalent of Debian Live GNOME
' --essential-hook=>$1/etc/initramfs-tools/conf.d/zstd echo COMPRESS=zstd ' ,
# '--include=live-task-gnome',
#'--include=live-task-xfce',
# Be the equivalent of Debian Live GNOME
# FIXME: enable this? It makes live-task-xfce go from 1G to 16G... so no.
# '--include=live-task-gnome',
#'--aptopt=Apt::Install-Recommends "true"',
#'--include=live-task-xfce',
# ...cherry-pick instead
# FIXME: enable this? It makes live-task-xfce go from 1G to 16G... so no.
# UPDATE: debian-installer-launcher DOES NOT WORK because we don't load crap SPECIFICALLY into /live/installer, in the ESP.
#'--aptopt=Apt::Install-Recommends "true"',
# UPDATE: network-manager-gnome DOES NOT WORK, nor is systemd-networkd auto-started... WTF?
# ...cherry-pick instead
# end result is no networking.
# UPDATE: debian-installer-launcher DOES NOT WORK because we don't load crap SPECIFICALLY into /live/installer, in the ESP.
#'--include=live-config user-setup sudo firmware-linux haveged',
# UPDATE: network-manager-gnome DOES NOT WORK, nor is systemd-networkd auto-started... WTF?
#'--include=calamares-settings-debian udisks2', # 300MB weirdo Qt GUI debian installer
# end result is no networking.
#'--include=xfce4-terminal',
#'--include=live-config user-setup sudo firmware-linux haveged',
# x86_64 CPUs are undocumented proprietary RISC chips that EMULATE a documented x86_64 CISC ISA.
#'--include=calamares-settings-debian udisks2', # 300MB weirdo Qt GUI debian installer
# The emulator is called "microcode", and is full of security vulnerabilities.
#'--include=xfce4-terminal',
# Make sure security patches for microcode for *ALL* CPUs are included.
# By default, it tries to auto-detect the running CPU, so only patches the CPU of the build server.
# x86_64 CPUs are undocumented proprietary RISC chips that EMULATE a documented x86_64 CISC ISA.
" --include=intel-microcode amd64-microcode iucode-tool " ,
# The emulator is called "microcode", and is full of security vulnerabilities.
" --essential-hook=>$1/etc/default/intel-microcode echo IUCODE_TOOL_INITRAMFS=yes IUCODE_TOOL_SCANCPUS=no " ,
# Make sure security patches for microcode for *ALL* CPUs are included.
" --essential-hook=>$1/etc/default/amd64-microcode echo AMD64UCODE_INITRAMFS=yes " ,
# By default, it tries to auto-detect the running CPU, so only patches the CPU of the build server.
" --dpkgopt=force-confold " , # Work around https://bugs.debian.org/981004
' --include=intel-microcode amd64-microcode iucode-tool ' ,
# DHCP/DNS/SNTP clients...
' --essential-hook=>$1/etc/default/intel-microcode echo IUCODE_TOOL_INITRAMFS=yes IUCODE_TOOL_SCANCPUS=no ' ,
# FIXME: use live-config ?
' --essential-hook=>$1/etc/default/amd64-microcode echo AMD64UCODE_INITRAMFS=yes ' ,
" --include=libnss-resolve libnss-myhostname systemd-timesyncd " ,
' --dpkgopt=force-confold ' , # Work around https://bugs.debian.org/981004
" --customize-hook=chroot $1 cp -alf /lib/systemd/resolv.conf /etc/resolv.conf " , # This probably needs to happen LAST
# FIXME: fix resolv.conf to point to resolved, not "copy from the build-time OS"
# DHCP/DNS/SNTP clients...
# FIXME: fix hostname & hosts to not exist, not "copy from the build-time OS"
# FIXME: use live-config ?
" --customize-hook=systemctl --root=$1 enable systemd-networkd systemd-timesyncd " , # is this needed?
' --include=libnss-resolve libnss-myhostname systemd-timesyncd ' ,
# Run a DHCP client on *ALL* ifaces.
' --customize-hook=chroot $1 cp -alf /lib/systemd/resolv.conf /etc/resolv.conf ' , # This probably needs to happen LAST
# Consider network "up" (start sshd and local login prompt) when *ANY* (not ALL) ifaces are up.
# FIXME: fix resolv.conf to point to resolved, not "copy from the build-time OS"
" --customize-hook=>$1/etc/systemd/network/up.network printf ' %s \n ' ' [Match] ' Name= ' en* ' ' [Network] ' DHCP=yes " , # try DHCP on all ethernet ifaces
# FIXME: fix hostname & hosts to not exist, not "copy from the build-time OS"
" --customize-hook=mkdir $1/etc/systemd/system/systemd-networkd-wait-online.service.d " ,
' --customize-hook=systemctl --root=$1 enable systemd-networkd systemd-timesyncd ' , # is this needed?
" --customize-hook=>$1/etc/systemd/system/systemd-networkd-wait-online.service.d/any-not-all.conf printf ' %s \n ' ' [Service] ' ' ExecStart= ' ' ExecStart=/lib/systemd/systemd-networkd-wait-online --any ' " ,
# Run a DHCP client on *ALL* ifaces.
# Hope there's a central smarthost SMTP server called "mail" in the local search domain.
# Consider network "up" (start sshd and local login prompt) when *ANY* (not ALL) ifaces are up.
# FIXME: can live-config do this?
" --customize-hook=>$1/etc/systemd/network/up.network printf ' %s \n ' ' [Match] ' Name= ' en* ' ' [Network] ' DHCP=yes " , # try DHCP on all ethernet ifaces
" --include=msmtp-mta " ,
' --customize-hook=mkdir $1/etc/systemd/system/systemd-networkd-wait-online.service.d ' ,
" --customize-hook=>$1/etc/msmtprc printf ' %s \n ' ' account default ' ' syslog LOG_MAIL ' ' host mail ' ' auto_from on ' " ,
" --customize-hook=>$1/etc/systemd/system/systemd-networkd-wait-online.service.d/any-not-all.conf printf ' %s \n ' ' [Service] ' ' ExecStart= ' ' ExecStart=/lib/systemd/systemd-networkd-wait-online --any ' " ,
# Hope there's a central RELP logserver called "logserv" in the local domain.
# FIXME: can live-config do this?
# Hope there's a central smarthost SMTP server called "mail" in the local search domain.
" --include=rsyslog-relp " ,
# FIXME: can live-config do this?
""" --customize-hook=>$1/etc/rsyslog.conf printf ' %s \n ' ' module(load= " imuxsock " ) ' ' module(load= " imklog " ) ' ' module(load= " omrelp " ) ' ' action(type= " omrelp " target= " logserv " port= " 2514 " template= " RSYSLOG_SyslogProtocol23Format " ) ' """ ,
' --include=msmtp-mta ' ,
# Run self-tests on all discoverable hard disks, and (try to) email if something goes wrong.
" --customize-hook=>$1/etc/msmtprc printf ' %s \n ' ' account default ' ' syslog LOG_MAIL ' ' host mail ' ' auto_from on ' " ,
" --include=smartmontools bsd-mailx " ,
" --customize-hook=>$1/etc/smartd.conf echo ' DEVICESCAN -n standby,15 -a -o on -S on -s (S/../../7/00|L/../01/./01) -t -H -m root -M once ' " ,
# Hope there's a central RELP logserver called "logserv" in the local domain.
# For rarely-updated, rarely-rebooted SOEs, apply what security updates we can into transient tmpfs COW.
# FIXME: can live-config do this?
# This CANNOT apply kernel security updates (though it will download them).
' --include=rsyslog-relp ' ,
# This CANNOT make the upgrades persistent across reboots (they re-download each boot).
""" --customize-hook=>$1/etc/rsyslog.conf printf ' %s \n ' ' module(load= " imuxsock " ) ' ' module(load= " imklog " ) ' ' module(load= " omrelp " ) ' ' action(type= " omrelp " target= " logserv " port= " 2514 " template= " RSYSLOG_SyslogProtocol23Format " ) ' """ ,
# FIXME: Would it be cleaner to set Environment=NEEDRESTART_MODE=a in
# apt-daily-upgrade.service and/or
# Run self-tests on all discoverable hard disks, and (try to) email if something goes wrong.
# unattended-upgrades.service, so
' --include=smartmontools bsd-mailx ' ,
# needrestart is noninteractive only when apt is noninteractive?
" --customize-hook=>$1/etc/smartd.conf echo ' DEVICESCAN -n standby,15 -a -o on -S on -s (S/../../7/00|L/../01/./01) -t -H -m root -M once ' " ,
" --include=unattended-upgrades needrestart " ,
" --customize-hook=echo ' unattended-upgrades unattended-upgrades/enable_auto_updates boolean true ' | chroot $1 debconf-set-selections " ,
# For rarely-updated, rarely-rebooted SOEs, apply what security updates we can into transient tmpfs COW.
""" --customize-hook=>$1/etc/needrestart/conf.d/unattended-needrestart.conf echo ' $nrconf {restart} = " a " ; ' """ , # https://bugs.debian.org/894444
# This CANNOT apply kernel security updates (though it will download them).
# Do an apt update & apt upgrade at boot time (as well as @daily).
# This CANNOT make the upgrades persistent across reboots (they re-download each boot).
# The lack of /etc/machine-id causes these to be implicitly enabled.
# FIXME: Would it be cleaner to set Environment=NEEDRESTART_MODE=a in
# FIXME: use dropin in /etc.
# apt-daily-upgrade.service and/or
" --customize-hook=>>$1/lib/systemd/system/apt-daily.service printf ' %s \n ' ' [Install] ' ' WantedBy=multi-user.target ' " ,
# unattended-upgrades.service, so
" --customize-hook=>>$1/lib/systemd/system/apt-daily-upgrade.service printf ' %s \n ' ' [Install] ' ' WantedBy=multi-user.target ' " ,
# needrestart is noninteractive only when apt is noninteractive?
# FIXME: add support for this stuff (for the non-live final install this happens via ansible):
' --include=unattended-upgrades needrestart ' ,
#
" --customize-hook=echo ' unattended-upgrades unattended-upgrades/enable_auto_updates boolean true ' | chroot $1 debconf-set-selections " ,
# unattended-upgrades
""" --customize-hook=>$1/etc/needrestart/conf.d/unattended-needrestart.conf echo ' $nrconf {restart} = " a " ; ' """ , # https://bugs.debian.org/894444
# smartd
# Do an apt update & apt upgrade at boot time (as well as @daily).
# networkd (boot off ANY NIC, not EVERY NIC -- https://github.com/systemd/systemd/issues/9714)
# The lack of /etc/machine-id causes these to be implicitly enabled.
# refind (bootloader config)
# FIXME: use dropin in /etc.
# misc safety nets
" --customize-hook=>>$1/lib/systemd/system/apt-daily.service printf ' %s \n ' ' [Install] ' ' WantedBy=multi-user.target ' " ,
# double-check that mmdebstrap's machine-id support works properly
" --customize-hook=>>$1/lib/systemd/system/apt-daily-upgrade.service printf ' %s \n ' ' [Install] ' ' WantedBy=multi-user.target ' " ,
# Bare minimum to let me SSH in.
# FIXME: make this configurable.
# FIXME: add support for this stuff (for the non-live final install this happens via ansible):
# FIXME: trust a CA certificate instead -- see Zero Trust SSH, Jeremy Stott, LCA 2020 <https://youtu.be/lYzklWPTbsQ>
#
# WARNING: tinysshd does not support RSA, nor MaxStartups, nor sftp (unless you also install openssh-client, which is huge).
# unattended-upgrades
# FIXME: double-check no host keys are baked into the image (openssh-server and dropbear do this).
# smartd
" --include=tinysshd rsync " ,
# networkd (boot off ANY NIC, not EVERY NIC -- https://github.com/systemd/systemd/issues/9714)
" --essential-hook=install -dm700 $1/root/.ssh " ,
# refind (bootloader config)
' --essential-hook=echo " ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIapAZ0E0353DaY6xBnasvu/DOvdWdKQ6RQURwq4l6Wu twb@cyber.com.au (Trent W. Buck) " >$1/root/.ssh/authorized_keys ' ,
# misc safety nets
# Bare minimum to let me log in locally.
# double-check that mmdebstrap's machine-id support works properly
# DO NOT use this on production builds!
" --essential-hook=chroot $1 passwd --delete root " ,
# Bare minimum to let me SSH in.
# Configure language (not needed to boot).
# FIXME: make this configurable.
# Racism saves a **LOT** of space -- something like 2GB for Debian Live images.
# FIXME: trust a CA certificate instead -- see Zero Trust SSH, Jeremy Stott, LCA 2020 <https://youtu.be/lYzklWPTbsQ>
# FIXME: use live-config instead?
# WARNING: tinysshd does not support RSA, nor MaxStartups, nor sftp (unless you also install openssh-client, which is huge).
" --include=locales localepurge " ,
# FIXME: double-check no host keys are baked into the image (openssh-server and dropbear do this).
f " --essential-hook=echo locales locales/default_environment_locale select { args . locale } | chroot $1 debconf-set-selections " ,
' --include=tinysshd rsync ' ,
f " --essential-hook=echo locales locales/locales_to_be_generated multiselect { args . locale } UTF-8 | chroot $1 debconf-set-selections " ,
' --essential-hook=install -dm700 $1/root/.ssh ' ,
# FIXME: https://bugs.debian.org/603700
' --essential-hook=echo " ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIapAZ0E0353DaY6xBnasvu/DOvdWdKQ6RQURwq4l6Wu twb@cyber.com.au (Trent W. Buck) " >$1/root/.ssh/authorized_keys ' ,
" --customize-hook=chroot $1 sed -i /etc/locale.nopurge -e ' s/^USE_DPKG/#ARGH#&/ ' " ,
" --customize-hook=chroot $1 localepurge " ,
# Bare minimum to let me log in locally.
" --customize-hook=chroot $1 sed -i /etc/locale.nopurge -e ' s/^#ARGH#// ' " ,
# DO NOT use this on production builds!
# Removing documentation also saves a LOT of space.
' --essential-hook=chroot $1 passwd --delete root ' ,
" --dpkgopt=path-exclude=/usr/share/doc/* " ,
" --dpkgopt=path-exclude=/usr/share/info/* " ,
# Configure language (not needed to boot).
" --dpkgopt=path-exclude=/usr/share/man/* " ,
# Racism saves a **LOT** of space -- something like 2GB for Debian Live images.
" --dpkgopt=path-exclude=/usr/share/omf/* " ,
# FIXME: use live-config instead?
" --dpkgopt=path-exclude=/usr/share/help/* " ,
' --include=locales localepurge ' ,
" --dpkgopt=path-exclude=/usr/share/gnome/help/* " ,
f ' --essential-hook=echo locales locales/default_environment_locale select { args . locale } | chroot $1 debconf-set-selections ' ,
# Configure timezone (not needed to boot)`
f ' --essential-hook=echo locales locales/locales_to_be_generated multiselect { args . locale } UTF-8 | chroot $1 debconf-set-selections ' ,
# FIXME: use live-config instead?
# FIXME: https://bugs.debian.org/603700
" --include=tzdata " ,
" --customize-hook=chroot $1 sed -i /etc/locale.nopurge -e ' s/^USE_DPKG/#ARGH#&/ ' " ,
f " --essential-hook=echo tzdata tzdata/Areas select { args . timezone [ 0 ] } | chroot $1 debconf-set-selections " ,
" --customize-hook=chroot $1 localepurge " ,
f " --essential-hook=echo tzdata tzdata/Zones/ { args . timezone [ 0 ] } select { args . timezone [ 1 ] } | chroot $1 debconf-set-selections " ,
" --customize-hook=chroot $1 sed -i /etc/locale.nopurge -e ' s/^#ARGH#// ' " ,
# 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).
# Removing documentation also saves a LOT of space.
# We can't use mkfs.udf, as that needs mount (i.e. root).
' --dpkgopt=path-exclude=/usr/share/doc/* ' ,
# We can't use "refind-install --usedefault" as that runs mount(8) (i.e. root).
' --dpkgopt=path-exclude=/usr/share/info/* ' ,
# We don't use genisoimage because
' --dpkgopt=path-exclude=/usr/share/man/* ' ,
# 1) ISO9660 must die;
' --dpkgopt=path-exclude=/usr/share/omf/* ' ,
# 2) incomplete UDF 1.5+ support;
' --dpkgopt=path-exclude=/usr/share/help/* ' ,
# 3) resulting filesystem can't be tweaked after flashing (e.g. debian-live/site.dir/etc/systemd/network/up.network).
' --dpkgopt=path-exclude=/usr/share/gnome/help/* ' ,
#
# 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.
# Configure timezone (not needed to boot)`
# If you want kernel+initrd on something other than FAT, you need refind/drivers_xxx/xxx_xxx.EFI.
# FIXME: use live-config instead?
#
' --include=tzdata ' ,
# FIXME: with qemu in UEFI mode (OVMF), I get dumped into startup.nsh (UEFI REPL).
f ' --essential-hook=echo tzdata tzdata/Areas select { args . timezone [ 0 ] } | chroot $1 debconf-set-selections ' ,
# From there, I can manually type in "FS0:\EFI\BOOT\BOOTX64.EFI" to start refind, tho.
f ' --essential-hook=echo tzdata tzdata/Zones/ { args . timezone [ 0 ] } select { args . timezone [ 1 ] } | chroot $1 debconf-set-selections ' ,
# 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 " ,
# Do the **BARE MINIMUM** to make a USB key that can boot on X86_64 UEFI.
" --customize-hook=echo refind refind/install_to_esp boolean true | chroot $1 debconf-set-selections " ,
# We use mtools so we do not ever need root privileges.
" --customize-hook=chroot $1 mkdir -p /boot/USB /boot/EFI/BOOT " ,
# We can't use mkfs.vfat, as that needs kpartx or losetup (i.e. root).
" --customize-hook=chroot $1 cp /usr/share/refind/refind/refind_x64.efi /boot/EFI/BOOT/BOOTX64.EFI " ,
# We can't use mkfs.udf, as that needs mount (i.e. root).
" --customize-hook=chroot $1 cp /usr/share/refind/refind/refind.conf-sample /boot/EFI/BOOT/refind.conf " ,
# We can't use "refind-install --usedefault" as that runs mount(8) (i.e. root).
f " --customize-hook=chroot $1 truncate --size= { filesystem_img_size } /boot/USB/filesystem.img " ,
# We don't use genisoimage because
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 " ,
# 1) ISO9660 must die;
f " --customize-hook=chroot $1 mformat -i /boot/USB/filesystem.img@@ { esp_offset } -F -v { esp_label } " ,
# 2) incomplete UDF 1.5+ support;
f " --customize-hook=chroot $1 mmd -i /boot/USB/filesystem.img@@ { esp_offset } :: { live_media_path } " ,
# 3) resulting filesystem can't be tweaked after flashing (e.g. debian-live/site.dir/etc/systemd/network/up.network).
f """ --customize-hook=echo ' " Boot with default options " " boot=live live-media-path= { live_media_path } " ' >$1/boot/refind_linux.conf """ ,
#
f """ --customize-hook=chroot $1 find /boot/ -xdev -mindepth 1 -maxdepth 1 -not -name filesystem.img -not -name USB -exec mcopy -vsbpm -i /boot/USB/filesystem.img@@ { esp_offset } {{ }} :: ' ; ' """ ,
# We use refind because 1) I hate grub; and 2) I like refind.
# FIXME: copy-out doesn't handle sparseness, so is REALLY slow (about 50 seconds).
# If you want aarch64 or ia32 you need to install their BOOTxxx.EFI files.
# Therefore instead leave it in the squashfs, and extract it later.
# If you want kernel+initrd on something other than FAT, you need refind/drivers_xxx/xxx_xxx.EFI.
# f'--customize-hook=copy-out /boot/USB/filesystem.img /tmp/',
#
# f'--customize-hook=chroot $1 rm /boot/USB/filesystem.img',
# FIXME: with qemu in UEFI mode (OVMF), I get dumped into startup.nsh (UEFI REPL).
" sid " ,
# From there, I can manually type in "FS0:\EFI\BOOT\BOOTX64.EFI" to start refind, tho.
td / " filesystem.squashfs " ,
# 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 ' ,
with args . output_file . open ( " wb " ) as f :
' --customize-hook=chroot $1 mkdir -p /boot/USB /boot/EFI/BOOT ' ,
subprocess . check_call (
' --customize-hook=chroot $1 cp /usr/share/refind/refind/refind_x64.efi /boot/EFI/BOOT/BOOTX64.EFI ' ,
[ " rdsquashfs " , " --cat=boot/USB/filesystem.img " , td / " filesystem.squashfs " ] ,
' --customize-hook=chroot $1 cp /usr/share/refind/refind/refind.conf-sample /boot/EFI/BOOT/refind.conf ' ,
stdout = f ,
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 ' ,
subprocess . check_call (
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 } ' ,
" mcopy " ,
f """ --customize-hook=echo ' " Boot with default options " " boot=live live-media-path= { live_media_path } " ' >$1/boot/refind_linux.conf """ ,
" -i " ,
f " { args . output_file } @@ { esp_offset } " ,
f """ --customize-hook=chroot $1 find /boot/ -xdev -mindepth 1 -maxdepth 1 -not -name filesystem.img -not -name USB -exec mcopy -vsbpm -i /boot/USB/filesystem.img@@ { esp_offset } {{ }} :: ' ; ' """ ,
td / " filesystem.squashfs " ,
# FIXME: copy-out doesn't handle sparseness, so is REALLY slow (about 50 seconds).
f " :: { live_media_path } /filesystem.squashfs " ,
# 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',
' sid ' ,
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 ' ] )