Auto-rotate the deploy Forgejo runner registration token #510

Closed
opened 2026-07-09 22:00:05 +00:00 by coilyco-ops · 2 comments
Member

Problem

The forgejo-runner-deploy StatefulSet persists /data/.runner on its PVC. That means deleting the pod does not necessarily rotate the runner's auth token. Manual rotation is available, but the deploy runner is high-impact because it carries the deploy:host label and runs with cluster deploy access.

Desired behavior

Add automatic bounded rotation for the deploy runner registration:

  • Keep the current persistent runner behavior across ordinary restarts.
  • Add a TTL check around /data/.runner in deploy/forgejo-runner-deploy.yml.
  • When the runner config is older than the chosen TTL, remove it before registration so the init container mints/registers a fresh runner token.
  • Prefer a conservative TTL, for example 30 days, unless repo docs or Forgejo runner behavior suggest a better interval.
  • Preserve the deploy:host label.
  • Avoid logging token material.
  • Update docs if this materially changes runner operations.

Context

This follows infrastructure#357. That issue covered a one-time exposed .runner token for forgejo-runner-deploy-0; this issue is the structural follow-up so future runner auth tokens do not live indefinitely on the PVC.

## Problem The `forgejo-runner-deploy` StatefulSet persists `/data/.runner` on its PVC. That means deleting the pod does not necessarily rotate the runner's auth token. Manual rotation is available, but the deploy runner is high-impact because it carries the `deploy:host` label and runs with cluster deploy access. ## Desired behavior Add automatic bounded rotation for the deploy runner registration: - Keep the current persistent runner behavior across ordinary restarts. - Add a TTL check around `/data/.runner` in `deploy/forgejo-runner-deploy.yml`. - When the runner config is older than the chosen TTL, remove it before registration so the init container mints/registers a fresh runner token. - Prefer a conservative TTL, for example 30 days, unless repo docs or Forgejo runner behavior suggest a better interval. - Preserve the `deploy:host` label. - Avoid logging token material. - Update docs if this materially changes runner operations. ## Context This follows infrastructure#357. That issue covered a one-time exposed `.runner` token for `forgejo-runner-deploy-0`; this issue is the structural follow-up so future runner auth tokens do not live indefinitely on the PVC.
Author
Member

WARD-RESERVATION: held 🔒

reservation details

Holder: container engineer-codex-infrastructure-510 on host kais-macbook-pro-2.local.

Reserved by ward agent --harness codex (reserved 2026-07-09T22:00:11Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (1h TTL). --force overrides.

Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh. That is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).

run seed context — what this run is carrying (ward#609)
  • Resolved: coilyco-flight-deck/infrastructure#510 · branch issue-510 · harness codex · workflow direct-to-main
  • Run: engineer-codex-infrastructure-510 · ward v0.493.0 · dispatched 2026-07-09T22:00:11Z
  • Comment thread: 0 included in the pre-flight read, 0 stripped (ward's own automated comments).

Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.493.0).

— Codex, via ward agent

<!-- ward-agent-reservation --> WARD-RESERVATION: held 🔒 <details><summary>reservation details</summary> Holder: container `engineer-codex-infrastructure-510` on host `kais-macbook-pro-2.local`. Reserved by `ward agent --harness codex` (reserved 2026-07-09T22:00:11Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (1h TTL). `--force` overrides. **Do not comment on or edit this issue to steer the run while it is reserved.** The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a **new issue, dispatched fresh**. That is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494). <details><summary>run seed context — what this run is carrying (ward#609)</summary> - **Resolved:** `coilyco-flight-deck/infrastructure#510` · branch `issue-510` · harness `codex` · workflow `direct-to-main` - **Run:** `engineer-codex-infrastructure-510` · ward `v0.493.0` · dispatched `2026-07-09T22:00:11Z` - **Comment thread:** 0 included in the pre-flight read, 0 stripped (ward's own automated comments). Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.493.0). </details> </details> <!-- ward-agent-signature --> — Codex, via `ward agent`
Author
Member

WARD-OUTCOME: done

details

workflow: direct-to-main; review summary: review gate skipped by ~/.ward/config.yaml default

Implemented bounded rotation for deploy/forgejo-runner-deploy.yml so the deploy runner keeps persistent registration across normal restarts, but drops stale /data/.runner after 30 days and re-mints the token on the next start. The docs now say that explicitly.

It felt straightforward in the manifest and slightly noisy in the merge path because main moved while the run was in flight.

Confidence: high.

Surprises: the container ran out of disk for pre-commit and the merge hook could not write to /opt/uv, so validation had to fall back to git diff --check plus sh -n on the init script.

Follow-ups: none.

WARD-OUTCOME: done ✅ <details><summary>details</summary> workflow: direct-to-main; review summary: review gate skipped by `~/.ward/config.yaml` default Implemented bounded rotation for `deploy/forgejo-runner-deploy.yml` so the deploy runner keeps persistent registration across normal restarts, but drops stale `/data/.runner` after 30 days and re-mints the token on the next start. The docs now say that explicitly. It felt straightforward in the manifest and slightly noisy in the merge path because `main` moved while the run was in flight. Confidence: high. Surprises: the container ran out of disk for `pre-commit` and the merge hook could not write to `/opt/uv`, so validation had to fall back to `git diff --check` plus `sh -n` on the init script. Follow-ups: none. </details>
Sign in to join this conversation.
No description provided.