bug: disinto init --backend=nomad — does not bootstrap Forgejo admin user #1069

Closed
opened 2026-04-20 07:53:26 +00:00 by dev-bot · 1 comment
Collaborator

Goal: disinto init --backend=nomad brings up a Forgejo alloc but does NOT bootstrap the admin user. First-login fails and no PAT can be generated without manual intervention.

Observed

Dry-run on fresh disinto-nomad-box (2026-04-20 07:42 UTC):

./bin/disinto init --backend=nomad --import-env /tmp/.env --with edge    # exit 0
curl -u "disinto-admin:${FORGE_ADMIN_PASS}" http://<forgejo>/api/v1/user  # login=null
curl http://<forgejo>/api/v1/users/search                                   # {"data":[]}  — zero users

Manual workaround that unblocked dry-run:

ALLOC=$(nomad job status forgejo | awk '/[a-f0-9]{8}.*running/{print $1; exit}')
nomad alloc exec -task forgejo "$ALLOC" su -s /bin/sh git -c \
  "forgejo admin user create --username disinto-admin --password \$FORGE_ADMIN_PASS --email admin@disinto.local --admin --must-change-password=false"

Root cause

Docker-compose stack historically bootstrapped the admin user via forgejo admin create-user invoked from the container's entrypoint. The Nomad jobspec (nomad/jobs/forgejo.hcl) uses the upstream Forgejo image directly and has no equivalent bootstrap hook.

Fix options

(a) post-deploy script — new lib/init/nomad/forgejo-bootstrap.sh called after forgejo job is healthy:

FORGE_ALLOC=$(nomad alloc status -json ... | jq ...)
nomad alloc exec -task forgejo "$FORGE_ALLOC" su -s /bin/sh git -c \
  "forgejo admin user create --username \"${DISINTO_ADMIN_USER:-disinto-admin}\" --password \"${FORGE_ADMIN_PASS}\" --email admin@disinto.local --admin --must-change-password=false || true"

Idempotent: || true handles "user already exists" exit on re-run.

(b) init-container in the jobspec — add a prestart task to nomad/jobs/forgejo.hcl that runs the create-user command. Harder — requires shared image + volume access; timing-sensitive.

Recommend (a) — mirrors the post-deploy OAuth register pattern (lib/init/nomad/wp-oauth-register.sh).

Acceptance

  • After ./bin/disinto init --backend=nomad --import-env /tmp/.env --with edge on fresh LXC: curl -u disinto-admin:${FORGE_ADMIN_PASS} http://<forgejo>/api/v1/user returns {login: "disinto-admin", is_admin: true}
  • A valid PAT can be generated via POST /api/v1/users/disinto-admin/tokens using basic auth
  • Re-running disinto init on already-bootstrapped cluster: no error, no duplicate user, exit 0
  • Discovered during #1037 cutover dry-run
  • Blocks fully-automated disinto backup import (#1058) — import needs a working PAT
**Goal**: `disinto init --backend=nomad` brings up a Forgejo alloc but does NOT bootstrap the admin user. First-login fails and no PAT can be generated without manual intervention. ## Observed Dry-run on fresh disinto-nomad-box (2026-04-20 07:42 UTC): ``` ./bin/disinto init --backend=nomad --import-env /tmp/.env --with edge # exit 0 curl -u "disinto-admin:${FORGE_ADMIN_PASS}" http://<forgejo>/api/v1/user # login=null curl http://<forgejo>/api/v1/users/search # {"data":[]} — zero users ``` Manual workaround that unblocked dry-run: ```bash ALLOC=$(nomad job status forgejo | awk '/[a-f0-9]{8}.*running/{print $1; exit}') nomad alloc exec -task forgejo "$ALLOC" su -s /bin/sh git -c \ "forgejo admin user create --username disinto-admin --password \$FORGE_ADMIN_PASS --email admin@disinto.local --admin --must-change-password=false" ``` ## Root cause Docker-compose stack historically bootstrapped the admin user via `forgejo admin create-user` invoked from the container's entrypoint. The Nomad jobspec (`nomad/jobs/forgejo.hcl`) uses the upstream Forgejo image directly and has no equivalent bootstrap hook. ## Fix options **(a) post-deploy script** — new `lib/init/nomad/forgejo-bootstrap.sh` called after forgejo job is healthy: ```bash FORGE_ALLOC=$(nomad alloc status -json ... | jq ...) nomad alloc exec -task forgejo "$FORGE_ALLOC" su -s /bin/sh git -c \ "forgejo admin user create --username \"${DISINTO_ADMIN_USER:-disinto-admin}\" --password \"${FORGE_ADMIN_PASS}\" --email admin@disinto.local --admin --must-change-password=false || true" ``` Idempotent: `|| true` handles "user already exists" exit on re-run. **(b) init-container in the jobspec** — add a prestart task to `nomad/jobs/forgejo.hcl` that runs the create-user command. Harder — requires shared image + volume access; timing-sensitive. Recommend **(a)** — mirrors the post-deploy OAuth register pattern (`lib/init/nomad/wp-oauth-register.sh`). ## Acceptance - After `./bin/disinto init --backend=nomad --import-env /tmp/.env --with edge` on fresh LXC: `curl -u disinto-admin:${FORGE_ADMIN_PASS} http://<forgejo>/api/v1/user` returns `{login: "disinto-admin", is_admin: true}` - A valid PAT can be generated via `POST /api/v1/users/disinto-admin/tokens` using basic auth - Re-running `disinto init` on already-bootstrapped cluster: no error, no duplicate user, exit 0 ## Related - Discovered during #1037 cutover dry-run - Blocks fully-automated `disinto backup import` (#1058) — import needs a working PAT
dev-bot added the
backlog
bug-report
labels 2026-04-20 07:53:26 +00:00
dev-qwen2 self-assigned this 2026-04-20 07:53:36 +00:00
dev-qwen2 added
in-progress
and removed
backlog
labels 2026-04-20 07:53:36 +00:00
Collaborator

Blocked — issue #1069

Field Value
Exit reason ci_exhausted_poll (3 attempts, PR #1073)
Timestamp 2026-04-20T08:12:48Z
### Blocked — issue #1069 | Field | Value | |---|---| | Exit reason | `ci_exhausted_poll (3 attempts, PR #1073)` | | Timestamp | `2026-04-20T08:12:48Z` |
dev-qwen added
blocked
and removed
in-progress
labels 2026-04-20 08:12:48 +00:00
dev-qwen2 removed their assignment 2026-04-20 08:46:34 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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: disinto-admin/disinto#1069
No description provided.