Forgejo-native CI: a ci-box tenant and a forgejo-runner command family #109

Closed
opened 2026-07-27 20:24:45 +00:00 by claude-bot-andresmgsl · 0 comments

What

rig's CI story is GitHub-shaped end to end. This tracks making it work against
a self-hosted Forgejo instance (forgejo.heavyduty.builders), so a CI box
can be minted and registered without GitHub in the loop.

Three pieces:

  1. A forge-agnostic template registry fetch. templates_resolve in
    commands/lib/templates.sh hardcodes https://github.com/$repo/archive/....
    A registry hosted on Forgejo cannot be fetched at all today.
  2. A ci-box tenant definition — the box guest that runs CI jobs, defined
    in the registry like every other tenant.
  3. rig forgejo-runner install|status|remove — the operator-run
    registration half, mirroring the bootstrap runner-serverrunner install
    rhythm that already exists for GitHub.

Why a tenant, not a machine role

The topology is: a fleet machine hosts boxes, one of those boxes is the CI box,
and the forgejo-runner lives inside it. That is a -box tenant by rig's own
family rule (#76), and the box boundary does the isolation work that
docker-in-docker is usually standing in for. bootstrap-tenant.sh already
installs Docker in every tenant and puts the tenant user in the docker group,
so job containers work with no dind layer, no privileged: true, and no
tcp://…:2375.

rig runner * stays exactly as it is. Forgejo registers against an instance
and the token carries the scope, so there is no --repo to converge toward —
the two runners differ in substance, not just in URL.

Blocker: the instance is sign-in-gated

templates_resolve states a contract in its own comments:

the fetch is unauthenticated by contract (box auto-runs bootstrap at mint,
holding nothing)

Measured against forgejo.heavyduty.builders, anonymous access to
heavy-duty/rig — which the API reports as private: false — returns 404
for the API, the web page, the git remote, and /archive/<ref>.tar.gz. Only an
authenticated request succeeds.

So a Forgejo-hosted registry cannot be fetched at mint time until the instance
serves public repos anonymously:

FORGEJO__service__REQUIRE_SIGNIN_VIEW=false

That is a Coolify env-var change on the Forgejo service, alongside the
FORGEJO__actions__ENABLED=true the Actions setup already needs. It is an
operator action, not code, and it gates piece 2 above.

Out of scope

GitHub coupling in rig is wider than the registry — install.sh hardcodes
github.com in the latest-release redirect, both archive-URL builders, and the
snapshot fetch; commands/bootstrap.sh pulls box from
raw.githubusercontent.com. Those are separate follow-ups, filed rather than
folded in.

## What rig's CI story is GitHub-shaped end to end. This tracks making it work against a self-hosted **Forgejo** instance (`forgejo.heavyduty.builders`), so a CI box can be minted and registered without GitHub in the loop. Three pieces: 1. **A forge-agnostic template registry fetch.** `templates_resolve` in `commands/lib/templates.sh` hardcodes `https://github.com/$repo/archive/...`. A registry hosted on Forgejo cannot be fetched at all today. 2. **A `ci-box` tenant definition** — the box guest that runs CI jobs, defined in the registry like every other tenant. 3. **`rig forgejo-runner install|status|remove`** — the operator-run registration half, mirroring the `bootstrap runner-server` → `runner install` rhythm that already exists for GitHub. ## Why a tenant, not a machine role The topology is: a fleet machine hosts boxes, one of those boxes is the CI box, and the forgejo-runner lives inside it. That is a `-box` tenant by rig's own family rule (#76), and the box boundary does the isolation work that docker-in-docker is usually standing in for. `bootstrap-tenant.sh` already installs Docker in every tenant and puts the tenant user in the `docker` group, so job containers work with no dind layer, no `privileged: true`, and no `tcp://…:2375`. `rig runner *` stays exactly as it is. Forgejo registers against an *instance* and the token carries the scope, so there is no `--repo` to converge toward — the two runners differ in substance, not just in URL. ## Blocker: the instance is sign-in-gated `templates_resolve` states a contract in its own comments: > the fetch is unauthenticated by contract (box auto-runs bootstrap at mint, > holding nothing) Measured against `forgejo.heavyduty.builders`, anonymous access to `heavy-duty/rig` — which the API reports as `private: false` — returns **404** for the API, the web page, the git remote, and `/archive/<ref>.tar.gz`. Only an authenticated request succeeds. So a Forgejo-hosted registry cannot be fetched at mint time until the instance serves public repos anonymously: ``` FORGEJO__service__REQUIRE_SIGNIN_VIEW=false ``` That is a Coolify env-var change on the Forgejo service, alongside the `FORGEJO__actions__ENABLED=true` the Actions setup already needs. It is an operator action, not code, and it gates piece 2 above. ## Out of scope GitHub coupling in rig is wider than the registry — `install.sh` hardcodes `github.com` in the latest-release redirect, both archive-URL builders, and the snapshot fetch; `commands/bootstrap.sh` pulls box from `raw.githubusercontent.com`. Those are separate follow-ups, filed rather than folded in.
claude-bot-andresmgsl added the
enhancement
scope:installer
scope:runner
labels 2026-07-27 21:37:31 +00: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: heavy-duty/rig#109
No description provided.