Make allod site usable from a fork #51

Closed
opened 2026-09-10 15:12:10 +01:00 by vnprc-agent · 0 comments
Contributor

Give a fork the whole allod site lifecycle, not just the binary: today the command is compiled into the public host toolchain, but the credential it reads has no public placement mechanism, previewing a site is a command nobody discovers, and rotating the credential is a hand recipe. A fork that builds allod site deploy has no supported way to feed it a credential.

Primary goals:

  • The credential is a contract, not a private module — the identity template names the host user's credential files, and the framework places them; a deployment supplies ciphertext and nothing else.
  • Preview where sites are edited — one command that serves a site with the generator version its build pins, on machines that hold no credential.
  • Rotation through the same tool as every other host secret — rotate-token learns the rclone stanza, so the recipe in a deployment's docs retires.
  • Nothing lands twice — the order below keeps a running host from having the secret declared by both a deployment module and the framework, or by neither.

Task list

  • allod/secrets#17 — nexusIdentity carries userForgejoTokenFile and siteHostingConfigFile, null in the template, with the shape documented.
  • allod/archetypes#74 — mkHypervisor declares the two agenix secrets from those fields, null meaning absent, with a check that exercises both branches.
  • allod/nexus#44 — the integration doc names the contract allod site deploy reads and where agenix places it.
  • allod/tools#180 — allod site preview, compiled untagged so dev machines carry it.
  • allod/nexus#42 — rotate-token learns the rclone remote stanza format.

Landing order: secrets, then archetypes (which reads the new fields with or null, so it also evaluates against an older secrets pin), then the nexus doc. tools#180 and nexus#42 are independent of that chain and of each other. A deployment that carries its own placement module today deletes it after its pin advance picks up the framework's; that step lives in the deployment, not here.

Current state and specifics

allod/tools#162–#165 (closed) gave the command its --config <path> contract, a check that authenticates without publishing, and a config lifecycle whose mutable actions refuse a symlink by design. That last property is what makes agenix placement work: the file at rclone's default path is a symlink agenix owns, the read-only actions follow it, and a rotation is a secrets change plus a rebuild.

The framework already has the shape for dev machines: mkDevVm takes tokenFile and httpsTokenFile from the identity (allod/archetypes flake.nix:260-261), null meaning opted out, and a check (dev-forge-opt-out, flake.nix:1191-1290) pins the exact generated age.secrets projection in both states. mkHypervisor (flake.nix:413-470) has no equivalent, and the public nexusIdentity (allod/secrets flake.nix:84-89) carries only forgeTokenFile = null.

Read from agenix at the pinned revision, and load-bearing for the module's own documentation: installSecret does mkdir -p on the custom path's parent as root and ln -sfT onto the path, so a hand-written regular file there is replaced in place; cleanup removes only the previous generation directory, so removing the declaration later leaves the symlink dangling.

Scope

In: the five children above and their order.

Out: a second generator for preview (trigger: a second generator in a site repository); a second hosting layout (allod/tools#165's trigger, a real second consumer); anything about the rented-host path in dev-plans/managed-service-machines.md.

Give a fork the whole `allod site` lifecycle, not just the binary: today the command is compiled into the public host toolchain, but the credential it reads has no public placement mechanism, previewing a site is a command nobody discovers, and rotating the credential is a hand recipe. A fork that builds `allod site deploy` has no supported way to feed it a credential. Primary goals: - **The credential is a contract, not a private module** — the identity template names the host user's credential files, and the framework places them; a deployment supplies ciphertext and nothing else. - **Preview where sites are edited** — one command that serves a site with the generator version its build pins, on machines that hold no credential. - **Rotation through the same tool as every other host secret** — `rotate-token` learns the rclone stanza, so the recipe in a deployment's docs retires. - **Nothing lands twice** — the order below keeps a running host from having the secret declared by both a deployment module and the framework, or by neither. ### Task list - [ ] allod/secrets#17 — `nexusIdentity` carries `userForgejoTokenFile` and `siteHostingConfigFile`, null in the template, with the shape documented. - [ ] allod/archetypes#74 — `mkHypervisor` declares the two agenix secrets from those fields, null meaning absent, with a check that exercises both branches. - [ ] allod/nexus#44 — the integration doc names the contract `allod site deploy` reads and where agenix places it. - [ ] allod/tools#180 — `allod site preview`, compiled untagged so dev machines carry it. - [ ] allod/nexus#42 — `rotate-token` learns the rclone remote stanza format. Landing order: secrets, then archetypes (which reads the new fields with `or null`, so it also evaluates against an older secrets pin), then the nexus doc. tools#180 and nexus#42 are independent of that chain and of each other. A deployment that carries its own placement module today deletes it after its pin advance picks up the framework's; that step lives in the deployment, not here. ### Current state and specifics `allod/tools`#162–#165 (closed) gave the command its `--config <path>` contract, a `check` that authenticates without publishing, and a `config` lifecycle whose mutable actions refuse a symlink by design. That last property is what makes agenix placement work: the file at rclone's default path is a symlink agenix owns, the read-only actions follow it, and a rotation is a secrets change plus a rebuild. The framework already has the shape for dev machines: `mkDevVm` takes `tokenFile` and `httpsTokenFile` from the identity (`allod/archetypes` `flake.nix:260-261`), null meaning opted out, and a check (`dev-forge-opt-out`, `flake.nix:1191-1290`) pins the exact generated `age.secrets` projection in both states. `mkHypervisor` (`flake.nix:413-470`) has no equivalent, and the public `nexusIdentity` (`allod/secrets` `flake.nix:84-89`) carries only `forgeTokenFile = null`. Read from agenix at the pinned revision, and load-bearing for the module's own documentation: `installSecret` does `mkdir -p` on the custom path's parent as root and `ln -sfT` onto the path, so a hand-written regular file there is replaced in place; cleanup removes only the previous generation directory, so removing the declaration later leaves the symlink dangling. ### Scope In: the five children above and their order. Out: a second generator for preview (trigger: a second generator in a site repository); a second hosting layout (allod/tools#165's trigger, a real second consumer); anything about the rented-host path in `dev-plans/managed-service-machines.md`.
vnprc closed this issue 2026-09-10 16:47:42 +01:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
allod/strategy#51
No description provided.