Prompt User to Create Admin Credentials
Most services need admin credentials before the user can sign in. The standard pattern pairs a setupOnInit watcher with a setAdminPassword action: the watcher surfaces a critical task when no password is stored, and the action — when the user runs it — generates, stores, and returns the credential. The same action handles later rotation.
Solution
In setupOnInit, read the file model where the admin password lives. When it is unset, call sdk.action.createOwnTask() with severity 'critical' pointing to the setAdminPassword action. The action is sdk.Action.withoutInput, visibility: 'enabled' so users can reach it for rotation, and its handler calls utils.getDefaultString(), writes the result to the store, and returns it as a group result (username unmasked + copyable, password masked + copyable).
The shape gives you:
- One source of truth. The action is the only place that generates and stores; the init watcher only decides whether to surface the task.
- Rotation for free. Re-running the action overwrites the stored password and returns the new one — the same action covers first-set and reset.
- Idempotent inits. Task creation is idempotent on its replay key, so
setupOnInitcan run on every container rebuild without spamming tasks.
When the upstream service requires the password to be applied via CLI or API (rather than read from the store at startup), wrap the work in sdk.SubContainer.withTemp() inside the action handler and run the upstream command before returning — see the Reset a Password recipe for the temp-subcontainer shape.
Reference: Initialization · Tasks · Actions
Examples
See startos/init/ and startos/actions/ in: canary (cleanest reference — watchCredentials.ts + setAdminPassword.ts), openclaw (setPassword.ts), vaultwarden (admin-token.ts), bisq, helipad, btcpayserver, lnbits, actual-budget, gitea (uses withInput to also take username/email; generates the password server-side).