Skip to content

Build pipeline

The Makefile exposes the full pipeline as independent stages. make all runs the non-interactive sequence in order. The selected provider owns base-image acquisition and the boot stack; Flashberry refuses to reuse provider state for a different provider, board, architecture, manifest, or design specification.

1. Check

make check CFG=flashberry.local.yml

Runs static checks, configuration validation, provider-manifest validation, and unit tests. Private config values are not copied into provider provenance.

2. Prepare binfmt

make prepare CFG=flashberry.local.yml

Ensures QEMU binfmt support is enabled inside the assembler environment. Host support can be tested separately with make check-host CFG=....

3. Acquire and stage the provider rootfs

make rootfs CFG=flashberry.local.yml

The default raspberry-pi-os provider downloads one exact Raspberry Pi OS Lite 64-bit stable image from the official Raspberry Pi downloads service. The artifact is pinned by URL and SHA-256 in providers/raspberry-pi-os.yml, cached under its digest, verified before use, and expanded into a provider-owned base disk image. Flashberry stages the vendor root filesystem for customization while retaining the vendor boot partition as the authoritative boot stack.

Provider source/boot metadata is recorded in tmp/provider/state.json. It contains the provider/board/architecture, design and provider-manifest hashes, base artifact URL/SHA-256, and verification state, but no user passwords, Wi-Fi PSKs, or hotspot passwords.

The explicit debian expert provider still uses mmdebstrap. Its raspi-firmware package owns config.txt, kernel/initramfs names, firmware, and DTBs. The image stage copies that generated boot tree verbatim instead of replacing it with Flashberry's historical hand-written config.txt.

archlinuxarm is a fail-closed Phase-2 scaffold. Because its upstream artifact is rolling, acquisition remains disabled until a signature or concrete digest is resolved. It never falls through to another provider's rootfs or boot files.

4. Configure in chroot

make configure CFG=flashberry.local.yml

The configured rootfs receives the provider-neutral customization layers:

  • locale, timezone, and hostname;
  • canonical user/root password semantics, supplementary groups, sudo policy, optional authorized keys, and a fail-closed root SSH password policy;
  • requested packages and SSH service policy;
  • optional first-boot root expansion;
  • overlays/rootfs/ content;
  • NetworkManager as the configured network backend, with legacy dhcpcd disabled when present;
  • an autoconnecting DHCP Ethernet profile scoped by the configured interface match patterns;
  • deterministic multi-profile Wi-Fi station selection and the fallback hotspot;
  • flashberry-ip, its initial address-state service, and the NetworkManager dispatcher refresh hook;
  • scripts from hooks/in-chroot.d/.

Wi-Fi credentials exist only in root-owned NetworkManager connection keyfiles. The runtime policy used by the first-boot controller contains connection IDs, SSIDs, priorities, and timing metadata but no password/PSK values. The historical standalone wpa_supplicant.conf provisioning path is removed.

For inspection before image assembly:

make shell CFG=flashberry.local.yml

5. Assemble or customize the image

make image CFG=flashberry.local.yml

For Raspberry Pi OS, Flashberry copies the checksum-verified vendor disk image, extends its root partition when image.size_gb is larger, and applies only the configured rootfs. /boot/firmware is excluded from replacement, and the boot partition is hashed before and after customization so unexpected mutation fails the build. The vendor partition table, firmware, kernel, DTBs, overlays, and boot configuration therefore stay coherent.

For Debian, Flashberry creates the image partitions itself but copies the raspi-firmware generated boot tree verbatim. If an upstream bcm2837-rpi-3-b.dtb is present while generated config.txt lacks upstream_kernel=1, image assembly fails rather than recreating the historical broken handoff.

The source/provider record is copied to out/<image-name>.base-provenance.json. Full image verification/provenance and the fail-closed flash gate are intentionally Phase 5.

6. Compress and checksum

make compress

Each out/*.img is compressed with Zstandard and receives a matching SHA-256 checksum file.