Hi,

I have now been successful with the kind help of Roland on MiniDebconf in Hamburg. I'd like to document the current state of the work here for future reference.

On Tue, Aug 26, 2025 at 08:53:10PM +0200, Marc Haber wrote:
I am trying to build a live image for the Raspberry Pi. The idea is to have a write protected system that I can use to protect my GnuPG key. Target medium is an M.2 SSD in an USB enclosure that has a write-protect switch.

We sat together with a Raspberry Pi 4 running sid, and used that one to build a live image. Roland kindly provided this build script:

export BUILD=smallest-build; \
export CODENAME=sid; \
export INSTALLER_ORIGIN=git;
export TMPDIR=/var/tmp/live; \
export ARCH=$(dpkg --print-architecture); \
mkdir -p ${TMPDIR}; \
mmdebstrap \
        --mode=unshare \
        
--include=live-build,git,debian-archive-keyring,mount,sqv,ca-certificates,eatmydata,auto-apt-proxy,apt-utils
 \
        --variant=essential \
        --customize-hook='copy-in /path/to/live-build/checkout /' \
        --chrooted-customize-hook='
    set -e; \
    chown -R 0:0 /live-build; \
    export LIVE_BUILD=/live-build; \
    mkdir -p /build_here; \
    cd /build_here; \
    /live-build/test/rebuild.sh --configuration ${BUILD} --debian-version 
${CODENAME} --installer-origin ${INSTALLER_ORIGIN}' \
        --customize-hook="download /build_here/live-image-${ARCH}.hybrid.iso 
${BUILD}_${CODENAME}_${INSTALLER_ORIGIN}.iso" \
        --customize-hook="download /build_here/summary.txt 
${BUILD}_${CODENAME}_${INSTALLER_ORIGIN}.summary.txt" \
        --customize-hook="download /build_here/lb_output.txt 
${BUILD}_${CODENAME}_${INSTALLER_ORIGIN}.lb_output.txt" \
        --customize-hook="download /build_here/live-image-${ARCH}.packages 
${BUILD}_${CODENAME}_${INSTALLER_ORIGIN}.packages.txt" \
        ${CODENAME} /dev/null

When run on the Raspi itself, this creates a smallest-build_sid_git.iso. Now the challege was to boot that.

My Debian on Raspi boots from the Raspi firmware to u-boot to grub-efi, so I already had a working grub on the SD card. In my setups, the firmware partition also doubles es ESP partition. That is a rather comfortable point to start with. All work was done with a serial console without having to use a keyboard/display console. Most of my Raspberry Pis are servers, so this is my native way to access the Raspi.

So i just had to copy the smallest-build_sid_git.iso to the ESP parition, reboot into grub, abort the regular boot of the installed, "normal" Debian and boot the iso from a regular grub command line using:

loopback loop (hd0,gpt1)/smallest-build_sid_git.iso
linux        (loop)/live/vmlinuz-7.0.3+deb14-arm64 boot=live components 
findiso=/smallest-build_sid_git.iso nosplash console=ttyS1,115200n8
initrd        (loop)/live/initrd.img-7.0.3+deb14-arm64
boot

That already brought me to a login prompt where login with the normal debian live credentials was possible.

Greetings
Marc




tl;dr how to set up the raspi from an empty medium:
# parted /dev/sda print
Model: Patriot M.2 P300 128 (scsi)
Disk /dev/sda: 128GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name         Flags
 1      1049kB  8591MB  8590MB  fat32        esp          msftdata
 2      8591MB  17.2GB  8590MB  ext4         boot
 3      17.2GB  128GB   111GB   ext4         persistence

sda1 gets mounted as /boot/efi
sda2 gets mounted as /boot/

copy /usr/lib/raspi-firmware/* from the raspi-firmware package to /boot/efi. copy /usr/lib/u-boot/rpi_arm64/u-boot.bin from the u-boot-rpi package to boot/efi.

/boot/efi/config.txt:
arm_64bit=1
enable_uart=1
upstream_kernel=1
kernel=u-boot.bin
uart_2ndstage=1

Install grub-efi-arm64 package
grub-install
That will install grub to:
/boot/efi/EFI/debian/shimaa64.efi
/boot/efi/EFI/debian/grubaa64.efi
/boot/efi/EFI/debian/mmaa64.efi
/boot/efi/EFI/debian/fbaa64.efi
/boot/efi/EFI/debian/BOOTAA64.CSV
/boot/efi/EFI/debian/grub.cfg
/boot/efi/EFI/BOOT/BOOTAA64.EFI

Put the menuentry in /boot/grub/custom.cfg
menuentry "debian live" {
    loopback loop_std (hd0,gpt1)/zg_sid_git.iso
    linux        (loop_std)/live/vmlinuz-7.0.3+deb14-arm64 boot=live components 
findiso=/zg_sid_git.iso nosplash console=ttyS1,115200n8 persistence
    initrd        (loop_std)/live/initrd.img-7.0.3+deb14-arm64
}

If I did not forget any stage of this mess, that should work.

--
-----------------------------------------------------------------------------
Marc Haber         | "I don't trust Computers. They | Mailadresse im Header
Leimen, Germany    |  lose things."    Winona Ryder | Fon: *49 6224 1600402
Nordisch by Nature |  How to make an American Quilt | Fax: *49 6224 1600421

Reply via email to