Authenticate the hosting remote in the deploy preflight #162

Closed
opened 2026-09-06 23:04:50 +01:00 by vnprc-agent · 1 comment
Contributor

Make allod site deploy prove the hosting credential works before it builds, so a rejected login fails in a second with a sentence the operator can act on rather than as a raw rclone error after a full site build.

Primary goals:

  • Authenticate in the preflight, not just enumerate — the check confirms the remote can log in and reach the docroot, instead of only confirming a stanza with that name exists.
  • One legible sentence per cause — no remote, unreadable config, rejected credential, and unreachable host are four different problems with four different remedies, and the operator should not have to read rclone's wording to tell them apart.
  • Never claim a partial write that did not happen — a login refused at connect time uploaded nothing, and saying otherwise sends the reader looking for damage.
  • No second tool to diagnose it — everything needed to understand a failure comes from allod, because rclone is deliberately not on the operator's PATH.

Current state and specifics

requireSiteRemote (cmd/allod/site.go:359) runs rclone listremotes and checks the listing names shared (cmd/allod/site.go:49). That proves a stanza exists. It does not open a connection, so a stanza containing a wrong user or password passes the preflight, the whole site is built, and the failure arrives from rclone:

Domain: example.com
Source: /nix/store/...-site
Target: shared:domains/example.com/public_html
CRITICAL: Failed to create file system for "shared:domains/example.com/public_html": NewFs: failed to make FTP connection to "<host>:21": 530 Login authentication failed
allod: rclone sync failed; shared:domains/example.com/public_html may be partially updated

Two defects are visible in that output. The build ran before anything checked whether the credential works, and the closing line is false: the connection was refused, so nothing was uploaded and the docroot cannot be partially updated. That line is emitted unconditionally at cmd/allod/site.go:464.

A command that both authenticates and confirms the destination is reachable — rclone lsd <remote>: or equivalent — subsumes the existing existence check, so this replaces requireSiteRemote rather than adding a second preflight.

Diagnosing the failure above required nix shell nixpkgs#rclone -c rclone config show, because the deployment installs rclone on the allod wrapper's PATH rather than the operator's. That is deliberate and worth keeping, and it means this command owns its own diagnostics or nobody has them.

Scope

In: the preflight, the messages it emits, and the wording of the post-sync failure. Credential creation, update and inspection are allod/tools#163. Making the credential declarative is allod/tools#164.

Make `allod site deploy` prove the hosting credential works before it builds, so a rejected login fails in a second with a sentence the operator can act on rather than as a raw rclone error after a full site build. Primary goals: - **Authenticate in the preflight, not just enumerate** — the check confirms the remote can log in and reach the docroot, instead of only confirming a stanza with that name exists. - **One legible sentence per cause** — no remote, unreadable config, rejected credential, and unreachable host are four different problems with four different remedies, and the operator should not have to read rclone's wording to tell them apart. - **Never claim a partial write that did not happen** — a login refused at connect time uploaded nothing, and saying otherwise sends the reader looking for damage. - **No second tool to diagnose it** — everything needed to understand a failure comes from `allod`, because `rclone` is deliberately not on the operator's PATH. ### Current state and specifics `requireSiteRemote` (`cmd/allod/site.go:359`) runs `rclone listremotes` and checks the listing names `shared` (`cmd/allod/site.go:49`). That proves a stanza exists. It does not open a connection, so a stanza containing a wrong user or password passes the preflight, the whole site is built, and the failure arrives from rclone: Domain: example.com Source: /nix/store/...-site Target: shared:domains/example.com/public_html CRITICAL: Failed to create file system for "shared:domains/example.com/public_html": NewFs: failed to make FTP connection to "<host>:21": 530 Login authentication failed allod: rclone sync failed; shared:domains/example.com/public_html may be partially updated Two defects are visible in that output. The build ran before anything checked whether the credential works, and the closing line is false: the connection was refused, so nothing was uploaded and the docroot cannot be partially updated. That line is emitted unconditionally at `cmd/allod/site.go:464`. A command that both authenticates and confirms the destination is reachable — `rclone lsd <remote>:` or equivalent — subsumes the existing existence check, so this replaces `requireSiteRemote` rather than adding a second preflight. Diagnosing the failure above required `nix shell nixpkgs#rclone -c rclone config show`, because the deployment installs rclone on the `allod` wrapper's PATH rather than the operator's. That is deliberate and worth keeping, and it means this command owns its own diagnostics or nobody has them. ### Scope In: the preflight, the messages it emits, and the wording of the post-sync failure. Credential creation, update and inspection are `allod/tools`#163. Making the credential declarative is `allod/tools`#164.
Author
Contributor

Measurement that narrows this issue, from the live failure that prompted it.

The credential storage path is not at fault. allod site config at cf384e8 was driven end to end against a real rclone with a deliberately awkward password (Tr1cky!Pass#with$pecials), and rclone reveal returned it byte for byte. The rclone obscure - handling, the TrimRight(line, "\r\n") on the terminal read (cmd/allod/site_config.go:371), and the stanza writer all round-trip correctly. That path had never been exercised against a real rclone before — it was written and tested entirely against stubs — so this was worth confirming rather than assuming.

So the live 530 Login authentication failed was a wrong value entered at the prompt, not a value corrupted in transit. Which is exactly the case this issue exists to catch: the preflight has to reject a credential the server refuses, and no amount of care in site config can substitute for asking the server.

A concrete defect for the messages half of this issue. cmd/allod/site_config.go:130 ends a successful configure with:

Check it with: rclone lsd shared:

The operator cannot run that. rclone is installed on the allod wrapper's PATH and not the user's, so it fails with rclone: command not found, which is what happened when the real failure was being diagnosed. Any advice this namespace prints has to be a command that exists for the person reading it. rclone lsd <remote>: is still the right probe — it just has to be something allod runs, not something the operator is told to run.

Measurement that narrows this issue, from the live failure that prompted it. **The credential storage path is not at fault.** `allod site config` at `cf384e8` was driven end to end against a real rclone with a deliberately awkward password (`Tr1cky!Pass#with$pecials`), and `rclone reveal` returned it byte for byte. The `rclone obscure -` handling, the `TrimRight(line, "\r\n")` on the terminal read (`cmd/allod/site_config.go:371`), and the stanza writer all round-trip correctly. That path had never been exercised against a real rclone before — it was written and tested entirely against stubs — so this was worth confirming rather than assuming. So the live `530 Login authentication failed` was a wrong value entered at the prompt, not a value corrupted in transit. Which is exactly the case this issue exists to catch: the preflight has to reject a credential the server refuses, and no amount of care in `site config` can substitute for asking the server. **A concrete defect for the messages half of this issue.** `cmd/allod/site_config.go:130` ends a successful configure with: Check it with: rclone lsd shared: The operator cannot run that. rclone is installed on the `allod` wrapper's PATH and not the user's, so it fails with `rclone: command not found`, which is what happened when the real failure was being diagnosed. Any advice this namespace prints has to be a command that exists for the person reading it. `rclone lsd <remote>:` is still the right probe — it just has to be something `allod` runs, not something the operator is told to run.
vnprc closed this issue 2026-09-09 20:11:53 +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/tools#162
No description provided.