Bring up a Raspberry Pi CM5
The Raspberry Pi Compute Module 5 is the SpaceOS reference board. SpaceOS owns
its whole boot path there. The board verifies a signed boot image, and
dm-verity checks the root filesystem block by
block. A new release boots on trial and falls back on its own, and unikernels
get real KVM under the Solo5 hvt tender. Use the CM5 to prove your deploy
flow on the bench before you move to a flight computer.
The CM5 is a commercial part, neither radiation-qualified nor hardened against fault injection. Fault injection is an attack that disturbs the chip on purpose, with a voltage or clock glitch for example, to make it skip an instruction such as a signature check.
Prerequisites
- A CM5 Dev Kit. It holds the module (BCM2712, four Cortex-A76 cores, 4 GB of RAM, 32 GB of eMMC), the IO board, a cooler and case, a 27 W USB-C power supply, and the USB-A to USB-C cable that flashing uses.
rpibooton your computer. It presents the module's eMMC as a USB mass-storage device.- Gigabit Ethernet between your computer and the board.
- The Space CLI, installed as the documentation home shows.
Choose a profile
Two content-addressed target profiles ship for the CM5. They make different trust claims, and a release signed for one does not serve the other:
| Profile | Boot policy | Rollback | Use |
|---|---|---|---|
cm5-dev | The board checks the customer signature, and the policy can be reversed. | A software trial and rollback record. | Development, provisioning rehearsal, fault injection. |
cm5 | The hash of the customer RSA key is written to one-time-programmable (OTP) memory, and the development key path is revoked. | A discrete TPM holds a rollback floor that only rises, and seals the node's secrets. | The locked deploy reference. |
On cm5, the rollback floor is a TPM 2.0 NV counter index: the TPM increments
it on command and can never decrement or reset it, even after the disk is
wiped. To seal a secret is to encrypt it so that the TPM releases it only
while chosen platform configuration registers (PCRs) hold expected values. A
PCR can only be extended, never set: extending computes
PCR := SHA-256(PCR || digest). Measuring a release means extending a PCR
with its identity, and space-init extends PCR 11 with the identity of the
release it booted.
Writing the key hash to OTP memory is permanent: a locked board cannot return
to cm5-dev. Start with cm5-dev, and move to cm5 once your provisioning
flow passes on the bench. A cm5 board is admitted only when its enrollment
and attestation prove the OTP and TPM claims. Enrollment records a board's OTP
key hash and TPM identity with the authority that admits it. Attestation is
the board proving which release it booted: its TPM signs a quote over PCR 11
with an attestation key the verifier enrolled. Neither step ships in the
current release.
Measured boot evidence
says when attestation arrives.
Verified boot sequence
The CM5 uses the Raspberry Pi native boot chain, not UEFI. Each stage checks the next:
- The boot ROM, the VideoCore firmware, and the EEPROM bootloader load
boot.imgand verify it againstboot.sigwith the customer RSA key. boot.imgcarries the kernel, the initramfs, the device tree, and the command line.- The initramfs verifies the SpaceOS boot manifest. The manifest is a SUIT envelope, the IETF format for signed firmware updates, that lists the SHA-256 digest of the kernel, initramfs, device tree, root filesystem, and service set. An Ed25519 signature covers the envelope, and the 32-byte digest it signs is the release's identity.
- dm-verity opens the read-only root against the root hash pinned as
verity.roothash=on the kernel command line inside the signedboot.img. It hashes each 4096-byte block with SHA-256 as it is read, checks it up the hash tree to that root hash, and fails the read on a mismatch.space-initthen takes over. - The runner launches each service only after checking its signature against the mission's pinned trust root.
The profile pins the firmware, bootloader, kernel, and device tree by digest, so a board with a different firmware set fails release planning.
Three keys sign at three levels, and none can stand in for another. The
Raspberry Pi customer RSA key makes boot.img bootable. The Ed25519 release
key binds the boot inputs into one manifest. The mission's Ed25519 and
ML-DSA-65 identity, the one space keys manages, authorizes the services that
run.
The chain has limits you should know before a review. The VideoCore firmware and
the EEPROM code are closed and run before any SpaceOS code, so they sit inside
the trusted base unmeasured. On the cm5 profile the TPM measures from the
initramfs onward. dm-verity covers the read-only root; deployment state and keys
are protected by the TPM-sealed key and the rollback counter instead.
Install the SpaceOS system image
- Connect the target with its profile and transport.
--always-reachablesuits a bench board on your network. A node reached over real passes names its orbit with--tleand its ground station with--station. With no--signing-key, the CLI generates a local bring-up key for the board:
space target connect cm5-bench --profile cm5-dev \ --endpoint ipn:7.1 --cla-address cm5-bench.local:4556 --always-reachable- Build a release and print its plan. A release names a release signing
identity; Port a Linux app
shows how to generate one. The plan assembles the flashable
cm5.imgand prints the release descriptor: the composition, the target, its profile, the board, the kernel, the device tree, and the paths ofcm5.img,boot.img, andboot.sig. It changes nothing on the board.
space build . -t app:release --release --signing-key release \ --rollback-index 1space deploy app:release --target cm5-bench --plan- Flash the first image by hand. Put the module in USB-boot mode as the CM5
IO board documentation describes, connect its USB-C port to your computer,
and run
rpiboot. The eMMC then appears as a disk on your computer. Writecm5.imgto that disk with Raspberry Pi Imager ordd, leave USB-boot mode, and power-cycle the board:
sudo rpibootThe image holds the firmware boot partition, the signed boot.img with its
boot.sig, and a content store with an active and a recovery system release,
so the board can fall back from its first boot onward.
- Deploy. Every later release crosses the network into the content store, boots on trial, and becomes the confirmed release only after its health checks pass. If the trial fails, the board returns to the last healthy release. The decision lives in the boot record, a mirrored record on a raw partition, authenticated with HMAC-SHA-256 under the board's 32-byte boot state key and framed by a CRC-32C. It names the confirmed release, the release on trial, and a last-known-good. Each trial boot spends one of three attempts, and a trial that runs out before its health checks confirm it boots the confirmed release again:
space deploy app:release --target cm5-benchspace show cm5-bench v1space show reads the deploy record back: each phase, when it was reached, and
the board's signed acknowledgements. The node signs its installed and
activated acknowledgements with its Ed25519 acknowledgement key, the one
space target connect records, and the ground checks them against the public
half.
Rehearse on the bench before you lock the board
Run these checks on a cm5-dev board, in this order, before you write anything
to OTP memory:
- Read back the flashed eMMC and compare its layout with the plan.
- Modify one byte of
boot.imgand confirm the board refuses to boot it. Corrupt the root filesystem and confirm dm-verity stops the boot. - Cut power during a transfer, during a store write, during a trial boot, and during the confirmation, and confirm the board recovers at each point.
- Deploy a valid update, an update signed with the wrong key, and an update that fails its health check. Confirm that only the first becomes the confirmed release.
- Check that you can back up, rotate, and revoke the customer RSA key under your own custody procedure.
Enrolling the customer key hash in OTP memory and revoking the development key
path are irreversible. Run them at the board with the Raspberry Pi provisioning
tools, as a deliberate step of their own. space deploy never performs them.
Smoke tests
Each profile declares a smoke test and its pass criteria. cm5-dev declares
cm5-dev-v1:
native-signed-boot: the board boots the signedboot.img.modified-image-rejection: the board refuses a modified one.dm-verity: the root filesystem is verified as it is read.hvt-workload: a signed workload runs under the Solo5hvttender.
The locked cm5 profile declares cm5-v1, which adds otp-locked-boot,
tpm2-sessions, nv-floor-replay-rejection, and sealed-secret-policy.
Run SpaceOS on Raspberry Pi OS instead
A CM5 can also keep Raspberry Pi OS (64-bit) and run SpaceOS as a set of
services on it, the daemon install
model. That board is a different target: it uses the hosted-linux profile,
Raspberry Pi OS keeps its own boot path, and SpaceOS verifies only its own
signed daemon bundle. hosted-linux declares runc alone. Never connect such
a board with cm5-dev, whose digest asserts the SpaceOS boot chain.
- Flash Raspberry Pi OS Lite (64-bit) to the eMMC with
rpibootand Raspberry Pi Imager, then boot it and finish the first-run setup. - Install the signed SpaceOS daemon bundle on the board.
--issuernames the public key that signed it, and nothing is written until the bundle verifies:
sudo space target install --bundle ./space-bundle --issuer ./issuer.pem- From your computer, connect the board as a target:
space target connect cm5-os --profile hosted-linux \ --endpoint ipn:8.1 --cla-address cm5-os.local:4556 --always-reachable