Make the hypervisor identity plural so a deployment can run more than one #89
Labels
No labels
blocked
bug
decision
duplicate
enhancement
help wanted
invalid
landed?
question
ready-to-merge
stale
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
allod/archetypes#89
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Let a deployment run more than one hypervisor by making the hypervisor identity an attrset keyed by machine name, the way the dev and privacy archetypes already are.
Primary goals:
secretsexportshypervisorIdentitieskeyed by machine name instead of the singletonnexusIdentity, so a deployment can declare a laptop hypervisor and a server hypervisor in one inventory.archetypesmerges hypervisor identities exactly as it mergesdevIdentitiesandprivacyIdentities, and the arity assert stops special-casing "plus one".Current state and specifics
secretsexports one hypervisor identity record,lib.nexusIdentity, andarchetypesbinds it into the identity set atflake.nix:607:The literal
nexuskey is being replaced bynexusIdentity.hostnamein the work for allod/archetypes#88, which frees the name but leaves the count at one.machineConfigurationsassertsidentityNames == machineNames(flake.nix:628), so a second machine of typehypervisorin inventory has no identity to bind and fails there, and the arity assert immediately belowflake.nix:607hard-codes+ 1.Nothing else in the framework assumes a single hypervisor:
mkHypervisor(flake.nix:506) is already a per-machine builder takingname,identityanddefinition, andprofilesalready keys hypervisor profile definitions by name.The trigger that decides when this is worth doing: a second machine of type
hypervisoris declared in any deployment's inventory. Until then the singleton costs nothing, and the contract is better written against a real second hypervisor than guessed at now.Scope
In scope: the
secretsexport (hypervisorIdentities, replacing or alongsidenexusIdentity), the merge and arity assert inarchetypes/flake.nix, and whatever in the deployment's forks keys off the singleton.Tracked elsewhere: freeing the hypervisor name from the literal
nexus, which lands with allod/archetypes#88.Refs allod/archetypes#88
The trigger this issue names is about to be met: a deployment is adding a headless server hypervisor beside its laptop hypervisor, to run the dev machines. Plural identities are necessary for that and not sufficient. Three more places assume one hypervisor, and a deployment that declared a second one after this issue landed as written would evaluate and still be wrong.
Read against the public masters on 2026-09-29.
allod/secretssecrets.nix: every entry is encrypted to the onehostKey;lib/pi-credential-recipients.nixtakes onehypervisorPublicKeyslistallod/inventoryflake.nix: a guest entry names no hypervisor, andvm-specs.jsonlists every guest.allod/nexusscripts/new-vm:5-9offers every key in that filenix/builders/dev.nix:69andnix/builders/privacy.nix:19hand every guestsecrets.lib.identity.hostPublicKeys;nix/builders/hypervisor.nix:30,59authorizes a hypervisor's own keys on itself;flake.nix:304does the same for the installer's rootWhat each one wants
Not this issue
Remote administration is a separate question and wants its own issue. The host module runs no sshd and opens no port (
allod/nexusnix/configuration.nix:126), which is the right posture for a machine someone sits at. A headless hypervisor needs a way in, and the shape already used for internet-facing machines fits: a module the machine imports, with noenableoption, so a hypervisor that does not import it has no listener by construction. A deployment can then assert its absence on the laptop with a build check.Suggested handling
Keep this issue as the canonical goal and either widen its scope to the three rows above or file one child for each. The first row should not land after the rest: between plural identities landing and recipients being split, declaring a second hypervisor encrypts every existing secret to it.
A correction to my comment above, and where the work stands.
Correction
I wrote that declaring a second hypervisor after plural identities land "encrypts every existing secret to it". That is wrong. Recipients come from the primary's key slot,
identity.hostPublicKeys(secrets.nix,lib/pi-credential-recipients.nix), not from the identity list. A second identity encrypts nothing new, and a second hypervisor decrypts nothing until a secret's recipient list names it. So plural identities are safe to land first and alone.The narrower rule that does hold: the primary's key slot must never hold a second hypervisor's key. A second hypervisor's host key is registered in
machine-host-keys.jsonlike any machine, and the primary is never registered there.Prepared, awaiting relay
Five branches cover this issue and the three gaps. Each is independent of the others: it evaluates against today's revisions of its inputs, so none needs a lock bump before it. With one hypervisor declared, every machine and the installer evaluate to the same derivation as before.
allod/secretsagent/hypervisor-identitieslib.hypervisorIdentitiesbesidelib.nexusIdentity; addsoperatorPublicKeysallod/secretsagent/hypervisor-recipient-coverageallod/inventoryagent/host-facthostfact on a guest; required once there is more than one hypervisorallod/archetypesagent/plural-hypervisorshostinvmFacts, derives authorized keys from itallod/nexusagent/host-guardRemote administration is separate: allod/nexus#68.
Left open by these changes
fork-safety.shwas not run on the archetypes branch; it belongs to the lock-bump path.Everything this issue asks for is on master: hypervisor identities are read as a set keyed by hostname, merged by the same rule as the dev and privacy archetypes through nix/identities.nix, and the arity assert no longer hardcodes one hypervisor. The three gaps from the comment above landed alongside: the host fact (inventory, vmFacts, the provisioning guard), authorization derived from it, and the recipient coverage check in secrets. The post-landing fixes are allod/archetypes#121, allod/nexus#70, allod/secrets#39 and allod/inventory#19, all closed. The one thing still open is the transitional fallback, allod/archetypes#122. This issue can be closed as completed by its author or a maintainer; my account cannot close it.
complete