Table of Contents
About
A lightweight, ARM-based system Raspberry Pi 4 eliminates distractions, reduce bloat, and enforce a minimalist, CLI-driven workflow that aligns with my core principles: automation, scripting, remote management.
- Offload workloads to cloud environments keeping my local setup minimal, secure, and under my full control.
- Low power consumption — run 24/7 with minimal electricity cost.
- Small enough to carry as a backup or travel dev machine.
- Managing encrypted boot, ZRAM, swap tuning, remote builds, and ARM-specific containers.
Raspberry Pi 4 Model B References:
RPI Boot Firmware
The "firmware" on Raspberry Pi plays a critical role in the boot process. It's a set of binary blobs (closed-source) that initialize the hardware and load the operating system.
The GPU firmware is closed and likely always will be due to Broadcom's policies.
Boot Sequence Overview on RPi4:
- BootROM inside the SoC, closed, hardcoded - looks for
bootcode.bin
on the SD card. bootcode.bin
initializes the GPU and loadsstart4.elf
.start4.elf
parsesconfig.txt
, initializes memory layout, then loadskernel8.img
.kernel8.img
is loaded into RAM, and the ARM CPU is released to start executing it.
On early RPI models and on some Linux distributions RPI boot filenames can be without numeric suffix: start.elf
, kernel.img
.
The firmware files bootcode.bin
, start4.elf
, fixup.dat
are closed-source because:
- It runs on the GPU (VideoCore IV), not the ARM CPU. The initial stages of the boot process run entirely on the VideoCore GPU, a proprietary Broadcom IP. This includes memory init, SD card init, HDMI setup, etc.
- Broadcom owns the GPU IP and SDK. Raspberry Pi is built around Broadcom SoCs (e.g., BCM2711). The GPU firmware relies on Broadcom’s proprietary libraries, which Raspberry Pi Ltd. is not allowed to open-source.
- Licensing and NDA restrictions. GPU drivers and firmware involve NDAs and licensed tools, which prevent redistribution or public access to source code.
Some components are partially open:
- The bootloader on Raspberry Pi 4/5 (in EEPROM) is open-source: https://github.com/raspberrypi/rpi-eeprom
- The Linux kernel and device tree after the firmware hands off control are open source.
- The userland firmware interface raspi-config, overlays, etc. are in open GitHub repos.
U-Boot can be used after the GPU firmware loads it. But even then, you still need the GPU firmware to load U-Boot.
RPi4 VPU reverse engineering is ongoing (slowly) via projects like vpu-tools, but they're far from complete.
Libre computing boards like Pine64, BeagleBone, or VisionFive offer better upstream and open firmware support.
Debian 12 Installation
This chapter is about Debian 12 (Not Raspberry Pi OS!) encrypted installation as a base system.
SD Card Preparation
Use lsblk
to get your SD card device path. Replace /dev/sdX with your actual device (e.g., /dev/sda or /dev/sdX).
If the device had a complex or conflicting previous layout, especially:
- LUKS encryption
- LVM
- ZFS or Btrfs with multiple partitions
- Previous GPT + MBR hybrid setups
Then you should wipe the device partitions to avoid any problems with your setup in future.
Step 1: Wipe all filesystem signatures (partitions and FS types):
sudo wipefs -a /dev/sdX
/dev/sdX: 8 bytes were erased at offset 0x00000052 (vfat): 46 41 54 33 32 20 20 20
/dev/sdX: 1 byte was erased at offset 0x00000000 (vfat): eb
/dev/sdX: 2 bytes were erased at offset 0x000001fe (vfat): 55 aa
Step 2: Overwrite the beginning of the disk to remove any residual partition data:
sudo dd if=/dev/zero of=/dev/sdX bs=512 count=2048 status=progress
2048+0 records in
2048+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.170478 s, 6.2 MB/s
Step 3: Recreate the GPT label (optional but recommended for clean state):
sudo parted /dev/sdX mklabel gpt
Optional: Wipe GPT backup at end of disk:
SECTORS=$(sudo blockdev --getsz /dev/sdX)
sudo dd if=/dev/zero of=/dev/sdX bs=512 count=33 seek=$((SECTORS - 33)) status=progress
Alternative: The sgdisk --zap-all
command is used to completely erase partition table information on a disk. Specifically, it removes GPT and MBR metadata, making the disk appear "unpartitioned" to partitioning tools.
sgdisk --zap-all /dev/sdX
Create Partitions
Create boot
and root
partitions:
sudo parted -a optimal /dev/sdX mkpart primary fat32 1MiB 256MiB
sudo parted -a optimal /dev/sdX mkpart primary ext4 256MiB 100%
sudo mkfs.vfat -F32 -n BOOT /dev/sdX1
LUKS Encryption
Setup LUKS and root FS:
sudo cryptsetup luksFormat /dev/sdX2
sudo cryptsetup open /dev/sdX2 rpi-sd-card
sudo mkfs.ext4 -L root /dev/mapper/rpi-sd-card
Mount encrypted SD card partition 2 to ${HOME}/mnt/rpi-sd-card
mountpoint.
Mount boot SD card partition 1 to ${HOME}/mnt/rpi-sd-card-boot
mountpoint.
Download And Unpack Debian Image
Download 20231109_raspi_4_bookworm.img.xz
image from Tested images and unpack it.
wget https://raspi.debian.net/tested/20231109_raspi_4_bookworm.img.xz
xz -d 20231109_raspi_4_bookworm.img.xz
Use fdisk
to see image partitions:
/sbin/fdisk -l 20231109_raspi_4_bookworm.img
Device Boot Start End Sectors Size Id Type
20231109_raspi_4_bookworm.img1 8192 1048575 1040384 508M c W95 FAT32 (LBA)
20231109_raspi_4_bookworm.img2 1048576 5119999 4071424 1.9G 83 Linux
Use parted
to see image partitions:
/sbin/parted 20231109_raspi_4_bookworm.img unit B print
Number Start End Size Type File system Flags
1 4194304B 536870911B 532676608B primary fat16 lba
2 536870912B 2621439999B 2084569088B primary ext4
Only one partition can be mounted at the same time. You need to switch between
boot
androot
partitions bellow.
To mount a partition from source image you need to specify Start
values from parted
output as offsets in mount
command:
mkdir -p ~/mnt/raspi-4-{boot,root}
sudo mount -o loop,offset=4194304 20231109_raspi_4_bookworm.img ${HOME}/mnt/raspi-4-boot
Copy Root Filesystem
Copy root filesystem from source image to SD card encrypted partition 2. Unmount ${HOME}/mnt/raspi-4-boot
if it is mounted right now and mount second (root) partition of the source image:
sudo umount ${HOME}/mnt/raspi-4-boot
sudo mount -o loop,offset=536870912B 20231109_raspi_4_bookworm.img ${HOME}/mnt/raspi-4-root
Mount empty encrypted root filesystem if it is not mounted yet:
sudo mount /dev/mapper/rpi-sd-card ${HOME}/mnt/rpi-sd-card
Copy root /
filesystem from Debian tested images to SD card encrypted partition:
sudo rm -r ${HOME}/mnt/rpi-sd-card/*
sudo rsync -aAXv --delete ${HOME}/mnt/raspi-4-root/ ${HOME}/mnt/rpi-sd-card/
Chroot And Configure Base System
Preparing a chroot
means setting up an isolated filesystem environment so you can safely or effectively run commands as if you were inside another system, such as a new Linux install or a different architecture (with qemu).
chroot
stands for change root — it redefines / (root) for the current process.
Prepare chroot:
sudo mount -o bind /dev ${HOME}/mnt/rpi-sd-card/dev
sudo mount -o bind /sys ${HOME}/mnt/rpi-sd-card/sys
sudo mount -t proc proc ${HOME}/mnt/rpi-sd-card/proc
sudo cp /usr/bin/qemu-aarch64-static ${HOME}/mnt/rpi-sd-card/usr/bin/
sudo chroot ${HOME}/mnt/rpi-sd-card /bin/bash
Inside chroot, install important packages and set root
password:
echo rpi-secure > /etc/hostname
apt-get update
apt install cryptsetup-initramfs initramfs-tools busybox
echo 'root:raspberry' | chpasswd
Please note that generating initramfs
can take significant time - approx. 5-10 minutes depending on your SD card speed.
Add an entry to the /etc/crypttab
file inside your chroot that tells target system to unlock an encrypted root partition on boot:
echo "rpiroot /dev/mmcblk1p2 none luks" >> /etc/crypttab
Write an /etc/fstab
file from within the chroot environment, where the root filesystem is encrypted using LUKS. And the boot partition is separate, typically unencrypted and formatted as vfat.
Inside chroot, create /etc/fstab
:
cat <<EOF > /etc/fstab
/dev/mapper/rpiroot / ext4 errors=remount-ro 0 1
/dev/mmcblk1p1 /boot vfat defaults 0 2
EOF
Regenerate all existing initramfs
images (initial RAM filesystem images) for all installed kernels on your system:
update-initramfs -c -k all
Copy Boot Filesystem
Outside chroot.
Raspberry Pi does not use GRUB or traditional bootloaders — instead, the GPU bootloader loads firmware directly from the FAT32 /boot
partition on the SD card.
Copy boot files from raspi-4
image:
sudo mount /dev/sdX1 ${HOME}/mnt/rpi-sd-card-boot
sudo cp -av ${HOME}/mnt/raspi-4-boot/* ${HOME}/mnt/rpi-sd-card-boot/
Add kernel and initrd image from your bootstrapped SD card partition:
sudo cp ${HOME}/mnt/rpi-sd-card/boot/vmlinuz-6.1.0-XX-arm64 ${HOME}/mnt/rpi-sd-card-boot/
sudo cp ${HOME}/mnt/rpi-sd-card/boot/initrd.img-6.1.0-XX-arm64 ${HOME}/mnt/rpi-sd-card-boot/
Modify kernel and initramfs parameters in ${HOME}/mnt/rpi-sd-card-boot/config.txt
:
# Switch the CPU from ARMv7 into ARMv8 (aarch64) mode
arm_64bit=1
enable_uart=1
upstream_kernel=1
kernel=vmlinuz-6.1.0-XX-arm64
initramfs initrd.img-6.1.0-XX-arm64
Modify ${HOME}/mnt/rpi-sd-card-boot/cmdline.txt
:
console=tty0 console=tty1,115200 root=/dev/mapper/rpiroot rw rootfstype=ext4 rootwait cryptopts=target=rpiroot,source=/dev/mmcblk1p2,luks init=/sbin/init debug
Unmount chroot filesystems and close encrypted partition:
sudo umount mnt/rpi-sd-card/dev
sudo umount mnt/rpi-sd-card/proc
sudo umount mnt/rpi-sd-card/sys
sudo umount mnt/rpi-sd-card
sudo cryptsetup close rpi-sd-card
sudo umount mnt/rpi-sd-card-boot
Insert your SD card in Raspberry PI 4 and enjoy encrypted root!
Frequent Mistakes
Wrong SD Card Block Device Number
On my Raspberry Pi 4 Model B the SD card reader is /dev/mmcblk1
. On previous models it can be /dev/mmcblk0
. If something goes wrong during boot process you will see correct block device identificator in kernel debug messages on screen.
In that case you just need to poweroff your Raspberry Pi SBC: Mount boot partition and encrypted root partition as described upper. Chroot. Set correct block device identificator in /etc/crypttab
and /etc/fstab
files (root partition). Set correct block device identificator in cmdline.txt
file (boot partition).
Don't forget to close encryted device using sudo cryptsetup close
command after unmount encrypted root partition.
Failed Systemd Service Blocks Boot Process
If you see failed to start rpi-reconfigure-raspi-firmware.service
error - poweroff your Raspberry Pi and. Mount encrypted root partition as described upper and chroot. Inside chroot disable rpi-reconfigure-raspi.firmware.service
SystemD service.
Don't forget to close encryted device using sudo cryptsetup close
command after unmount encrypted root partition.
Bootstrap
The term "bootstrap" has its roots in the idea of "pulling yourself up by your bootstraps" — starting with almost nothing and building up to a fully working system. In computing, bootstrap refers to the process of initializing a system from a minimal starting state to a fully operational environment.
Install necessary tools:
sudo apt install debootstrap qemu-user-static binfmt-support
Mount target SD card root partition in ${HOME}/mnt/bootstrap
.
Bootstrap:
sudo debootstrap --arch=arm64 --foreign bookworm ${HOME}/mnt/bootstrap http://deb.debian.org/debian
If you make mistake - you can clean up root filesystem and retry bootstrap. Exit chroot and unmount proc
, dev
and sys
. Remove all files in ${HOME}/mnt/bootstrap/
directory and bootstrap again:
sudo umount -lf ${HOME}/mnt/bootstrap/{proc,sys,dev/pts,dev} 2>/dev/null
rm -rf ${HOME}/mnt/bootstrap/*
sudo debootstrap --arch=arm64 --foreign bookworm ${HOME}/mnt/bootstrap http://deb.debian.org/debian