ci: stand up forge-runner-01 with DinD sidecar, fix doc label bug
Bootstrap script + compose + config checked in under ops/forgejo-runner/ so a second runner is a scripted setup. runner-setup.md corrects the register label format (<name>:docker://<image>, not bare names) and documents the Ubuntu systemd-resolved DNS gotcha. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5be7206a93
commit
6cf65f2c36
5 changed files with 114 additions and 37 deletions
|
|
@ -104,7 +104,7 @@ None of these nail the "your dad can set this up" experience. The installer wiza
|
||||||
- [x] Competitor analysis — see [docs/competitors.md](docs/competitors.md)
|
- [x] Competitor analysis — see [docs/competitors.md](docs/competitors.md)
|
||||||
- [x] Wizard flow spec — see [docs/wizard-flow.md](docs/wizard-flow.md)
|
- [x] Wizard flow spec — see [docs/wizard-flow.md](docs/wizard-flow.md)
|
||||||
- [x] Release process + CI — CalVer tags, conventional commits, Forgejo Actions (ruff, pytest, JSON, link checks), `26.0-alpha` tagged
|
- [x] Release process + CI — CalVer tags, conventional commits, Forgejo Actions (ruff, pytest, JSON, link checks), `26.0-alpha` tagged
|
||||||
- [ ] **Stand up Forgejo runner** — see [docs/runner-setup.md](docs/runner-setup.md) *(Daniel, next session — without this CI queues forever)*
|
- [x] Forgejo runner live on Proxmox VM (`forge-runner-01`, Ubuntu 24.04, Docker + DinD sidecar) — setup captured in [docs/runner-setup.md](docs/runner-setup.md) + [ops/forgejo-runner/](ops/forgejo-runner/)
|
||||||
- [ ] **Publish `26.0-alpha` Forgejo Release** — [releases/new](https://forgejo.sourcegate.online/daniel/homebase/releases/new), paste CHANGELOG section, tick Pre-release *(Daniel, next session)*
|
- [ ] **Publish `26.0-alpha` Forgejo Release** — [releases/new](https://forgejo.sourcegate.online/daniel/homebase/releases/new), paste CHANGELOG section, tick Pre-release *(Daniel, next session)*
|
||||||
- [ ] **Base OS bootable image** — Robert gets a minimal Arch image that boots, runs Docker, serves the installer webapp at `https://proksi.local` *(next blocker)*
|
- [ ] **Base OS bootable image** — Robert gets a minimal Arch image that boots, runs Docker, serves the installer webapp at `https://proksi.local` *(next blocker)*
|
||||||
- [ ] Installer wizard screens S5–S8 (domain, SSL, diagnostic, confirm)
|
- [ ] Installer wizard screens S5–S8 (domain, SSL, diagnostic, confirm)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ How to stand up a `forgejo-runner` so the CI workflow in `.forgejo/workflows/ci.
|
||||||
|
|
||||||
The runner is a long-running daemon that polls the Forgejo instance for queued jobs and runs them in Docker containers.
|
The runner is a long-running daemon that polls the Forgejo instance for queued jobs and runs them in Docker containers.
|
||||||
|
|
||||||
|
A ready-to-use bootstrap script and compose file live under [`ops/forgejo-runner/`](../ops/forgejo-runner/).
|
||||||
|
|
||||||
## Choosing a host
|
## Choosing a host
|
||||||
|
|
||||||
| Option | Good for | Trade-off |
|
| Option | Good for | Trade-off |
|
||||||
|
|
@ -20,32 +22,9 @@ Pick either the binary or the Docker container path. Docker is easier to upgrade
|
||||||
|
|
||||||
### Path A: Docker Compose (recommended)
|
### Path A: Docker Compose (recommended)
|
||||||
|
|
||||||
On the chosen host, create `~/forgejo-runner/compose.yml`:
|
Copy `ops/forgejo-runner/compose.yml` and `ops/forgejo-runner/config.yml` from this repo to the host, e.g. into `~/forgejo-runner/` (compose file) and `~/forgejo-runner/data/` (config file). The runner talks to a sidecar Docker-in-Docker container via `tcp://docker-in-docker:2375`, so the host's own Docker socket is not exposed to jobs.
|
||||||
|
|
||||||
```yaml
|
If the host is a fresh Ubuntu VM, run `ops/forgejo-runner/bootstrap.sh` first to install Docker Engine + the Compose plugin from the official repo.
|
||||||
services:
|
|
||||||
runner:
|
|
||||||
image: code.forgejo.org/forgejo/runner:6
|
|
||||||
container_name: forgejo-runner
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
- CONFIG_FILE=/data/config.yml
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
depends_on:
|
|
||||||
- docker-in-docker
|
|
||||||
command: /bin/sh -c "sleep 5; forgejo-runner daemon"
|
|
||||||
|
|
||||||
docker-in-docker:
|
|
||||||
image: docker:dind
|
|
||||||
container_name: forgejo-runner-dind
|
|
||||||
restart: unless-stopped
|
|
||||||
privileged: true
|
|
||||||
environment:
|
|
||||||
- DOCKER_TLS_CERTDIR=
|
|
||||||
command: dockerd -H tcp://0.0.0.0:2375 --tls=false
|
|
||||||
```
|
|
||||||
|
|
||||||
### Path B: Binary
|
### Path B: Binary
|
||||||
|
|
||||||
|
|
@ -61,22 +40,24 @@ sudo mv forgejo-runner-6.0.0-linux-amd64 /usr/local/bin/forgejo-runner
|
||||||
|
|
||||||
1. In the Forgejo web UI: go to **Site Administration → Actions → Runners → Create new Runner**. Copy the registration token. (For a repo-scoped runner instead, use **Repo Settings → Actions → Runners**.)
|
1. In the Forgejo web UI: go to **Site Administration → Actions → Runners → Create new Runner**. Copy the registration token. (For a repo-scoped runner instead, use **Repo Settings → Actions → Runners**.)
|
||||||
|
|
||||||
2. Register from the runner host:
|
2. Register from the runner host by running the registration inside a one-shot container so the output lands in the mounted `data/` directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
cd ~/forgejo-runner
|
||||||
|
docker run --rm -v "$PWD/data:/data" code.forgejo.org/forgejo/runner:6 \
|
||||||
forgejo-runner register \
|
forgejo-runner register \
|
||||||
--instance https://forgejo.sourcegate.online \
|
--instance https://forgejo.sourcegate.online \
|
||||||
--token <TOKEN> \
|
--token <TOKEN> \
|
||||||
--name homebase-runner-1 \
|
--name forge-runner-01 \
|
||||||
--labels docker,ubuntu-latest,self-hosted \
|
--labels 'docker:docker://catthehacker/ubuntu:act-latest,ubuntu-latest:docker://catthehacker/ubuntu:act-latest,self-hosted:docker://catthehacker/ubuntu:act-latest' \
|
||||||
--no-interactive
|
--no-interactive
|
||||||
```
|
```
|
||||||
|
|
||||||
This writes `.runner` (registration file) and `config.yml` into the current directory.
|
Labels *must* use the `<name>:docker://<image>` form — bare labels (`ubuntu-latest`) get stored as `ubuntu-latest:host`, which tells the runner to execute jobs directly inside the runner container (no Python, no git, nothing). `catthehacker/ubuntu:act-latest` is the common drop-in image with GitHub Actions tooling preinstalled.
|
||||||
|
|
||||||
3. Start the daemon (Docker: `docker compose up -d`; binary: `forgejo-runner daemon`).
|
3. Start the daemon: `docker compose up -d`.
|
||||||
|
|
||||||
4. Verify the runner shows up as **Idle** in Forgejo's admin Runners page.
|
4. Verify the runner shows up as **Idle** in Forgejo's admin Runners page and the log prints `runner: forge-runner-01, ..., declared successfully`.
|
||||||
|
|
||||||
## First CI run
|
## First CI run
|
||||||
|
|
||||||
|
|
@ -108,6 +89,7 @@ Save as `/etc/systemd/system/forgejo-runner.service`, then `sudo systemctl enabl
|
||||||
|
|
||||||
## Security notes
|
## Security notes
|
||||||
|
|
||||||
- The runner mounts `/var/run/docker.sock` which gives it root-equivalent access to the host. Run it on a machine you trust and nothing sensitive.
|
- Jobs run inside a Docker-in-Docker sidecar, not against the host's Docker socket. Still, DinD runs privileged — give the runner its own VM, not a shared host.
|
||||||
- Registration tokens are one-shot; a stolen token can't re-register after the runner is live.
|
- Registration tokens are one-shot; a stolen token can't re-register after the runner is live.
|
||||||
- Prefer repo-scoped runners over instance-wide if you're sharing the runner with other repos you don't control.
|
- Prefer repo-scoped runners over instance-wide if you're sharing the runner with other repos you don't control.
|
||||||
|
- Ubuntu's default systemd-resolved makes the host's stub resolver (`127.0.0.53`) inherit a LAN DNS server that Docker containers may not be able to reach. If container DNS fails, set explicit upstream DNS in `/etc/docker/daemon.json` (e.g. `{"dns": ["1.1.1.1", "8.8.8.8"]}`) and `sudo systemctl restart docker`.
|
||||||
|
|
|
||||||
43
ops/forgejo-runner/bootstrap.sh
Executable file
43
ops/forgejo-runner/bootstrap.sh
Executable file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Install Docker Engine + Compose plugin on a fresh Ubuntu 24.04 VM
|
||||||
|
# and prepare it to host a Forgejo Actions runner.
|
||||||
|
#
|
||||||
|
# Run as the target user (needs sudo). Idempotent.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "$(. /etc/os-release && echo "$ID")" != "ubuntu" ]]; then
|
||||||
|
echo "This script targets Ubuntu. Aborting." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Updating apt and installing prerequisites"
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y ca-certificates curl gnupg
|
||||||
|
|
||||||
|
echo "==> Adding Docker's official GPG key"
|
||||||
|
sudo install -m 0755 -d /etc/apt/keyrings
|
||||||
|
if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Adding Docker apt repository"
|
||||||
|
ARCH="$(dpkg --print-architecture)"
|
||||||
|
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"
|
||||||
|
echo "deb [arch=${ARCH} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${CODENAME} stable" \
|
||||||
|
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
|
||||||
|
echo "==> Installing Docker Engine + Compose plugin"
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
|
echo "==> Adding $USER to docker group"
|
||||||
|
sudo usermod -aG docker "$USER"
|
||||||
|
|
||||||
|
echo "==> Enabling docker service"
|
||||||
|
sudo systemctl enable --now docker
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Done. Log out and back in (or run 'newgrp docker') so group membership takes effect."
|
||||||
|
docker --version
|
||||||
|
docker compose version
|
||||||
22
ops/forgejo-runner/compose.yml
Normal file
22
ops/forgejo-runner/compose.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
services:
|
||||||
|
runner:
|
||||||
|
image: code.forgejo.org/forgejo/runner:6
|
||||||
|
container_name: forgejo-runner
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- DOCKER_HOST=tcp://docker-in-docker:2375
|
||||||
|
- CONFIG_FILE=/data/config.yml
|
||||||
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
|
depends_on:
|
||||||
|
- docker-in-docker
|
||||||
|
command: /bin/sh -c "sleep 5; forgejo-runner daemon --config /data/config.yml"
|
||||||
|
|
||||||
|
docker-in-docker:
|
||||||
|
image: docker:dind
|
||||||
|
container_name: forgejo-runner-dind
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
environment:
|
||||||
|
- DOCKER_TLS_CERTDIR=
|
||||||
|
command: dockerd -H tcp://0.0.0.0:2375 --tls=false
|
||||||
30
ops/forgejo-runner/config.yml
Normal file
30
ops/forgejo-runner/config.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
log:
|
||||||
|
level: debug
|
||||||
|
job_level: info
|
||||||
|
|
||||||
|
runner:
|
||||||
|
file: .runner
|
||||||
|
capacity: 1
|
||||||
|
timeout: 3h
|
||||||
|
insecure: false
|
||||||
|
fetch_timeout: 5s
|
||||||
|
fetch_interval: 2s
|
||||||
|
report_interval: 1s
|
||||||
|
labels: []
|
||||||
|
|
||||||
|
cache:
|
||||||
|
enabled: true
|
||||||
|
dir: ""
|
||||||
|
host: ""
|
||||||
|
port: 0
|
||||||
|
proxy_port: 0
|
||||||
|
|
||||||
|
container:
|
||||||
|
network: ""
|
||||||
|
privileged: false
|
||||||
|
valid_volumes: []
|
||||||
|
docker_host: "tcp://docker-in-docker:2375"
|
||||||
|
force_pull: false
|
||||||
|
|
||||||
|
host:
|
||||||
|
workdir_parent:
|
||||||
Loading…
Add table
Reference in a new issue