3 KiB
CI — Forgejo Actions (self-hosted, Tailscale-only admin)
Forgejo Actions is GitHub-Actions compatible at the workflow-syntax layer (derived from Gitea Actions, which re-uses the actions/* runtime via act). A workflow that runs on GH usually runs on Forgejo with only the runner labels and registry URLs changed. Pair with RULE 0.1 — KeiGit repos MUST stay on private Forgejo, never mirror to github.com.
Layout
Workflows live under .forgejo/workflows/*.yml (primary) — .gitea/workflows/ also works for legacy repos. Keep the same narrow split as GH:
ci.yml— build + testrelease.yml— tag-drivensecurity.yml— scheduled scanners
Self-hosted runner
Forgejo has no SaaS runner fleet — you provide the compute. Install forgejo-runner [VERIFIED: https://code.forgejo.org/forgejo/runner] on a node that is reachable ONLY over Tailscale.
Registration:
forgejo-runner register \
--no-interactive \
--instance http://100.91.246.53:3000 \
--name kgl-runner-01 \
--labels "self-hosted,linux,x64,docker" \
--token "$FORGEJO_RUNNER_TOKEN" # from secrets/runner.env (RULE 0.8)
FORGEJO_RUNNER_TOKEN stays in secrets/runner.env — reference via env name only, never paste the literal value.
Target in workflow:
jobs:
build:
runs-on: [self-hosted, linux, x64]
GitHub-compat surface
Works out of the box: actions/checkout@v4, actions/cache@v4, actions/setup-node@v4, Swatinem/rust-cache@v2, shell/docker steps, matrix, reusable workflows (uses: <forgejo-host>/<owner>/<repo>/.forgejo/workflows/<file>@<sha>).
Does NOT work: permissions: block (Forgejo token is scoped at the runner level, not per-job), OIDC federation to AWS/GCP (no JWKS endpoint served by Forgejo), GitHub-Marketplace actions that call api.github.com directly.
Workaround for OIDC: for cloud deploys from Forgejo, prefer short-lived STS tokens minted by a bastion that has an IAM role, passed into the runner via a sealed env file rotated daily.
Tailscale-only admin posture
Forgejo Web UI is http://100.91.246.53:3000, SSH is ssh://git@100.91.246.53:2222/.... Both on Tailscale CGNAT. NEVER bind Forgejo to a public IP — runner tokens, PATs, and repo contents are unfiled patent IP (RULE 0.1).
Key fingerprint for the existing KeiGit host: SHA256:TxHcs7YuEZiy4Gu0yZOoVidVqlvj8TPC+QgUGjmh0Mw labelled macbook.
Secrets
Forgejo repo secrets (Repo → Settings → Actions → Secrets) mirror GH secrets syntactically: ${{ secrets.FOO }}. Organisation-scope secrets also supported. Every secret still references the canonical ~/.claude/secrets/.env / secrets/*.env source — repo secrets are cache copies, rotated when the source rotates.
Forbidden
- Exposing Forgejo port 3000 or 2222 on a public IP
- Running
forgejo-runneron a host that is also a production application node - Mirroring a KeiGit repo to github.com to "get free CI" (RULE 0.1)
- Hard-coded runner tokens in workflow YAML (always
${{ secrets.* }})