# NBDE boot policy This document describes the Guix-side NBDE boot model used by Tribes nodes. ## Storage locations NBDE state is split across three places: - The LUKS header stores unlock methods: recovery keyslots, disposable local boot keyslots, and Clevis/Tang bindings. - The initrd stores generic unlock logic and helper programs. It must not store node-local boot key material. - `/boot/nbde/local-boot.key` stores the disposable local boot key when a node is allowed to unlock itself without Tang peers. Tang peer URLs and quorum settings are Clevis metadata in the LUKS header. They are not baked into the initrd. ## Boot partition key The initrd is built with generic logic to find the boot partition by UUID, mount it read-only, and try `nbde/local-boot.key` before falling back to Clevis/Tang and then interactive `cryptsetup`. The key path exposed in system facts is: ```json { "localBootKeyFile": "/boot/nbde/local-boot.key" } ``` The key bytes are not imported with `local-file`, so changing the local boot key does not require a Guix system rebuild or a new initrd generation. Only the fixed initrd reader logic is part of the system generation. Legion currently creates `/boot` as an ext4 filesystem for both BIOS and EFI nodes. EFI nodes also have a vfat `/boot/efi` partition, but the NBDE local boot key does not live there. ## Unlock methods Every managed NBDE node has a durable recovery secret controlled by the management layer. That secret is used for administrative LUKS operations such as adding local boot keys and binding Clevis pins. The local boot key is different: - it is generated when degraded local unlock is needed, - it is stored only on the node under `/boot/nbde/local-boot.key`, - it is not stored in Guix store items, - it is not stored in Legion state, - it only matters while the matching LUKS keyslot exists. ## State transitions When entering degraded local-key mode: 1. Generate a fresh local boot key. 2. Write it to `/boot/nbde/local-boot.key`. 3. Add it as a LUKS keyslot using the durable recovery secret. 4. Remove obsolete Clevis bindings. When leaving degraded mode: 1. Add the desired Clevis/Tang or Clevis SSS quorum binding. 2. Remove obsolete Clevis bindings after the new binding succeeds. 3. Remove the local boot keyslot with `cryptsetup luksRemoveKey`. 4. Best-effort overwrite `/boot/nbde/local-boot.key`, sync, and unlink it. The LUKS header is the source of truth. If the local keyslot was removed successfully, a leftover file under `/boot/nbde` is no longer an unlock secret. Overwriting before unlink is hygiene for cloud block devices and ext4, not a cryptographic erasure guarantee. ## Threat model Without Secure Boot, measured boot, or another trusted boot chain, an unencrypted `/boot` partition is readable by an attacker with disk access. A local key baked into an initrd on `/boot` and a local key stored as a separate file on `/boot` therefore have the same practical confidentiality level. The `/boot/nbde/local-boot.key` model is preferred because it keeps key rotation out of Guix system generation rebuilds and avoids copying secret bytes through the Guix store and boot-store staging paths. ## Boot-store staging The boot-store staging service remains necessary for kernel, initrd, and GRUB store references. GRUB can read `/boot` before the encrypted root is unlocked, but it cannot read `/gnu/store` on the encrypted root. Local boot key material is intentionally outside that mechanism. The initrd reader is staged as part of the normal system generation; the mutable key file is managed directly under `/boot/nbde`.