Files
self 14dc316dca feat: read local NBDE boot key from boot partition
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.
2026-05-19 13:42:27 +02:00

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.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:

{
  "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.