Publish an age key¶
Nerthus.Core (until cutover). This page describes the frozen system that runs today and is deleted at cutover. Replaced by: Instance secrets.
The secret tree cannot hold a secret until at least one real recipient exists, and publishing one is an act only its holder can perform: the private half must never be transmitted, so nobody can do it for you.
The four steps¶
- Generate the keypair on your own device.
The file starts with a comment line carrying the public half — # public key: age1….
-
Keep the private half. It never leaves that device, never goes in a repository, never goes in a message, never goes in a password manager shared with anybody else. Losing it loses every value encrypted to it, permanently.
-
Publish the public half yourself, as one line under your own block in the contributor store:
- Ask for it to be added to
.sops.yamland the tree re-keyed. That issops updatekeysover every file underci/,edge/,hosts/andservices/.
Two things about that last step¶
Adding or removing a recipient rewrites every ciphertext in the tree. The diff is large and has no content change in it — which is exactly the diff nobody reviews carefully. Review the recipient: lines and the creation_rules block; the selftest checks the rest, and it fails if any file was left behind by an updatekeys that did not reach it.
Removing a recipient is not revocation. A person removed from .sops.yaml can still read every value they ever decrypted. Removing them stops them reading new ciphertext and takes nothing back. A credential a departing holder could read has to be re-minted, and whether it must be is a policy question rather than a mechanic. #/sejf/dostepy says the same sentence to a reader.
Provenance is a fact about how the key was made¶
A key is real when its holder generated it on their own device and published the public half themselves. That is not something a bech32 check can tell you and it is not something the grammar records, so it has to be asked.
The estate currently publishes nine @klucz_szyfr lines and not one of them is a real recipient: one in the lore contributor store and eight in the moderator store, each labelled a development seed by its own comment. Treating one of them as a recipient would encrypt production credentials to a key somebody generated on a laptop for a test.
(Counted 2026-08-21. Earlier pages said eight, from a count taken before the moderator store's last roster edit; the total is what a grep over both files answers today.)
And no fixture may use one. Until 2026-08-21 the dashboard's test fixtures carried the private halves of three of those published keys, which made a development seed a committed secret as well as a weak one. They are synthetic now, and Nerthus.Core.Dashboard/tests/fixtures-throwaway.test.ts asserts that no key in a fixture appears in any roster file — the rule was stated long before anything checked it.
How many recipients¶
At least two, and not two people who share a household or a device. A vault with one recipient is a vault one lost laptop empties — permanently, because nothing else can decrypt it. 17-sejf H5 rules on the archive-key shares separately; this is the ordinary case.
Getting a value back out¶
Being a recipient is what lets you read the tree, and
The secret tree · Consume a credential is how. Short
version: sejf/Invoke-SejfEnv.ps1 puts a credential in a child process's environment and nothing
on disk; a tool that already uses Import-NerthusEnv.ps1 finds it automatically. Without an
identity on the machine those tools say «key X: not in .env and no age identity» rather than
failing vaguely — which is the message this page is the answer to.