Teach the NBDE mapped-device initrd logic to mount the boot partition and try /boot/nbde/local-boot.key at boot time instead of baking local key material into the initrd. Update system facts defaults, materialisation, tests, and NBDE documentation for the boot-key model.
3.6 KiB
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.keystores 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:
{
"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:
- Generate a fresh local boot key.
- Write it to
/boot/nbde/local-boot.key. - Add it as a LUKS keyslot using the durable recovery secret.
- Remove obsolete Clevis bindings.
When leaving degraded mode:
- Add the desired Clevis/Tang or Clevis SSS quorum binding.
- Remove obsolete Clevis bindings after the new binding succeeds.
- Remove the local boot keyslot with
cryptsetup luksRemoveKey. - 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.