Episode 2: Forgejo Actions — runner, Docker sandbox, own registry, locked-down deploy

This commit is contained in:
Maximilian Grimm 2026-08-19 22:21:20 +02:00
parent 06f8e8812e
commit 0341ae777d
8 changed files with 231 additions and 1 deletions

View file

@ -90,6 +90,56 @@ Outline → its postgres/redis.
**Is `latest` okay for images?**
For a homelab: pragmatic. For production: pin versions and read HARDENING.md.
## CI: your own runners (Episode 2)
Forgejo ships Actions. Turn it on, give it a runner, and you have GitHub Actions
with no minute counter.
```bash
# 1. Enable it (already set in compose.yml)
# FORGEJO__actions__ENABLED and repo.actions in DEFAULT_REPO_UNITS.
# Without repo.actions in the default units, the Actions tab stays hidden
# and it looks like the feature is broken. Existing repos: flip it per repo.
# 2. One shared secret for declarative registration
SECRET=$(openssl rand -hex 20)
UUID=$(python3 -c 'import uuid,sys;print(uuid.UUID(bytes=sys.argv[1][:16].encode()))' "$SECRET")
printf 'RUNNER_SECRET=%s\nRUNNER_UUID=%s\n' "$SECRET" "$UUID" >> .env
# 3. Tell Forgejo about it
docker compose exec -u git forgejo forgejo forgejo-cli actions register \
--name box-runner --labels docker --secret "$SECRET"
# 4. Fill in the runner config and start the CI profile
cp runner-config.example.yml runner-config.yml
sed -i "s|https://git.example.com|https://git.$DOMAIN|; s|\${RUNNER_UUID}|$UUID|; s|\${RUNNER_SECRET}|$SECRET|" runner-config.yml
docker compose --profile ci up -d
```
Then check Site Administration → Runners: the runner should be online with the
label `docker`.
**Four things that cost people an evening:**
- A registration **token from the web UI is not a shared secret**. The declarative
path above only accepts the secret you generated. Feed it the web token and the
runner connects and never receives a job, with no error anywhere.
- The `connections:` block lives under a top-level **`server:`** key in runner
13.x. Older examples put it under `runner:`, which fails with
`0 server connections configured`.
- **An empty `labels:` list means every job waits forever.** No error, just a
queued job and a healthy-looking runner.
- The image behind a label **must contain node** — Forgejo actions are JavaScript.
Pointing `docker` at a docker-cli image gives you
`node: executable file not found`. Use a node image and let the build job fetch
a static docker client (see `examples/ci.yml`).
`examples/ci.yml` is a complete pipeline: test, build a container, push it to
Forgejo's built-in registry, and deploy it over an SSH key that can only run one
command (`examples/deploy-hello-ops.sh`). Read the CI section of
[HARDENING.md](HARDENING.md) before you wire the deploy step — there are two
comfortable ways to hand your whole server to anyone who can push a branch.
## Hardening
Before you put real company data on this box, read **[HARDENING.md](HARDENING.md)**.