Skip to main content

Break-glass age key on paper

The target secrets scheme has a break-glass keypair that is a recipient on every .sops.yaml rule: with a clone of this repository, its secret half decrypts the whole store. That secret half lives on paper in a safe, and nowhere else.

Nothing to do yet

secretzone/ is still plaintext — there is nothing for this key to decrypt. The sheet gets produced when the migration starts, together with the .sops.yaml that lists it as a recipient. Generating it earlier only creates something to guard.

Why paper is the right medium

An age secret key is a 74-character string, AGE-SECRET-KEY-1…, and its public half is 62 characters. Both are bech32: the alphabet omits 1, B, I and O, so no glyph can be misread as l, 8 or 0, and the trailing checksum makes age refuse a mistyped key instead of accepting it as a different one. Typing it back takes about a minute, and needs nothing but the age binary — no plugin, no hardware, no service that has to still be running.

A FIDO2 token as break-glass recipient was rejected (Aug 2026): the identity it derives cannot be cloned, printed or restored, so a lost, dead or PIN-locked key would leave the store unreadable. Hardware tokens can still hold per-admin identities on top of the paper copy.

Producing the sheet

provisioning/secrets/break-glass-sheet.sh ~/break-glass # any directory outside a clone

Needs age and qrencode. The script generates the keypair, writes a printable A4 sheet (break-glass-sheet.html) and prints the public key to add to .sops.yaml. It refuses to write inside a git work tree or over existing files, and ends with the shred command for the on-disk copies — the files must not survive the printing.

The sheet carries the five things that are needed years later: the secret key as a QR code and grouped in eights for manual typing, the public key to check that transcription, the generation date, what the key opens, and the handling rules.

Storing it

Two copies, in two buildings, each sealed in a tamper-evident envelope signed across the flap. Laser print on plain paper — inkjet runs when damp, thermal paper fades. Not in room 23N307: the PDU probe read 76 °C there during the June 2026 heat event.

The secret key is never committed, never placed in secretzone/, and never generated on a shared or rack machine.

Restoring

On a machine with the repository and sops, write the key from the sheet into a file, check it against the printed public key, then decrypt:

umask 077; cat > /dev/shm/bg.key # type or scan the key, then Ctrl-D
age-keygen -y /dev/shm/bg.key # must match the public key on the sheet
SOPS_AGE_KEY_FILE=/dev/shm/bg.key sops -d secretzone/<file>.yaml
shred -u /dev/shm/bg.key

Keeping it valid

Test the restore once a year: retype the key from one sheet, decrypt one file, destroy the copy, re-seal. That test is where a 8 mistaken for a B surfaces, while it still doesn't matter.

Anyone holding the sheet can read every secret in the store, permanently, and there is no revocation. An envelope found open, lost, or unaccounted for means: generate a new keypair, run sops updatekeys over the store, and rotate the values themselves.