Teach rotate-token the rclone remote stanza so the site hosting credential rotates like the other host secrets #42

Closed
opened 2026-09-09 21:52:24 +01:00 by vnprc-agent · 0 comments

Let the shared-hosting FTP credential that allod site deploy reads rotate through rotate-token, so the one secret behind publishing follows the same tooled lifecycle as the forge tokens instead of a hand recipe in the deployment's secrets repository.

Primary goals:

  • A third secret format — rclone-remote-stanza beside raw-forgejo-token and credential-store-url (scripts/rotate-token:259-261, :337-345). The plaintext is the complete [shared] stanza that allod site config writes (type = ftp, host, user, pass, explicit_tls = true; allod/tools cmd/allod/site_config.go, remoteStanza), so the decrypted file is byte-compatible with what rclone reads at its default config path and no activation step reshapes it.
  • Rotate the password alone — as credential-store-url already does, decrypt the existing stanza to carry host and user forward, prompt only for the new password, and re-encrypt to the existing recipients. Retyping two correct fields to change a third is how the last live credential failure happened (allod/tools#163).
  • Obscure without exposing — rclone stores passwords only in its obscured form, and obscuring is reversible by anyone with rclone, so the obscured value is exactly as sensitive as the password. It is produced with rclone obscure - on stdin, never on argv, and never printed.
  • Verify with the server, with a command the operator has — the printed verification is allod site check, which authenticates the remote without publishing (allod/tools#162). rclone itself rides on the allod wrapper's PATH and not the operator's (nix/home.nix:92-114), so any rclone command in the advice would be command not found.
  • Registry-driven like the rest — the secret is described with the same fields the token-group registry uses (secret_path, format, targets[].deployed_path), so --group selects it and dry runs list it. Whether that registry stays Forgejo-named or grows a sibling for non-forge credentials is the open shape question; the default is the smallest change that lets prepare_item accept the new format.

Current state and specifics

prepare_item dies on any format other than the two it knows (scripts/rotate-token:259-261), and the per-item rotation switch has no branch for a stanza (:337-345). The credential-store branch already shows the pattern this needs: decrypt with the host identity, parse the fields to carry forward, take one new secret on a hidden prompt, rebuild the plaintext, encrypt to the recipients extracted from secrets.nix.

The host does not have rclone on the operator's PATH by design, so the script needs it as a runtime input of the provisioning-scripts package or must reach it through the wrapper. Adding it to the script's own inputs is the smaller and more honest change: the wrapper's PATH is an implementation detail of allod, not a contract.

The public secrets template (allod/secrets) has no site-hosting entry, and a deployment that publishes nothing should not gain one. The format lands here; the registry entry and the age file are each deployment's own.

Trigger: the first rotation of a site hosting credential after it has been created once by hand. Until that rotation is needed, the documented recipe (read the password silently, pipe through rclone obscure - into the stanza, pipe into age for the host key) is the path, and this issue is not blocking anything.

Scope

In: the format, its prompt and parse, the obscure step, the verification hint, and the registry shape that selects it.

Out: deployment-side wiring of the age file to rclone's config path, which is each deployment's private composition; creating a credential from nothing (allod site config owns that today, and an import of an existing config file into an age secret can follow separately); and any change to what allod site reads, which is settled by allod/tools#164.

Let the shared-hosting FTP credential that `allod site deploy` reads rotate through `rotate-token`, so the one secret behind publishing follows the same tooled lifecycle as the forge tokens instead of a hand recipe in the deployment's secrets repository. Primary goals: - **A third secret format** — `rclone-remote-stanza` beside `raw-forgejo-token` and `credential-store-url` (`scripts/rotate-token:259-261`, `:337-345`). The plaintext is the complete `[shared]` stanza that `allod site config` writes (`type = ftp`, `host`, `user`, `pass`, `explicit_tls = true`; allod/tools `cmd/allod/site_config.go`, `remoteStanza`), so the decrypted file is byte-compatible with what rclone reads at its default config path and no activation step reshapes it. - **Rotate the password alone** — as `credential-store-url` already does, decrypt the existing stanza to carry `host` and `user` forward, prompt only for the new password, and re-encrypt to the existing recipients. Retyping two correct fields to change a third is how the last live credential failure happened (allod/tools#163). - **Obscure without exposing** — rclone stores passwords only in its obscured form, and obscuring is reversible by anyone with rclone, so the obscured value is exactly as sensitive as the password. It is produced with `rclone obscure -` on stdin, never on argv, and never printed. - **Verify with the server, with a command the operator has** — the printed verification is `allod site check`, which authenticates the remote without publishing (allod/tools#162). rclone itself rides on the `allod` wrapper's PATH and not the operator's (`nix/home.nix:92-114`), so any rclone command in the advice would be `command not found`. - **Registry-driven like the rest** — the secret is described with the same fields the token-group registry uses (`secret_path`, `format`, `targets[].deployed_path`), so `--group` selects it and dry runs list it. Whether that registry stays Forgejo-named or grows a sibling for non-forge credentials is the open shape question; the default is the smallest change that lets `prepare_item` accept the new format. ### Current state and specifics `prepare_item` dies on any format other than the two it knows (`scripts/rotate-token:259-261`), and the per-item rotation switch has no branch for a stanza (`:337-345`). The credential-store branch already shows the pattern this needs: decrypt with the host identity, parse the fields to carry forward, take one new secret on a hidden prompt, rebuild the plaintext, encrypt to the recipients extracted from `secrets.nix`. The host does not have `rclone` on the operator's PATH by design, so the script needs it as a runtime input of the provisioning-scripts package or must reach it through the wrapper. Adding it to the script's own inputs is the smaller and more honest change: the wrapper's PATH is an implementation detail of `allod`, not a contract. The public secrets template (`allod/secrets`) has no site-hosting entry, and a deployment that publishes nothing should not gain one. The format lands here; the registry entry and the age file are each deployment's own. Trigger: the first rotation of a site hosting credential after it has been created once by hand. Until that rotation is needed, the documented recipe (read the password silently, pipe through `rclone obscure -` into the stanza, pipe into `age` for the host key) is the path, and this issue is not blocking anything. ### Scope In: the format, its prompt and parse, the obscure step, the verification hint, and the registry shape that selects it. Out: deployment-side wiring of the age file to rclone's config path, which is each deployment's private composition; creating a credential from nothing (`allod site config` owns that today, and an import of an existing config file into an age secret can follow separately); and any change to what `allod site` reads, which is settled by allod/tools#164.
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/nexus#42
No description provided.