Files
cargoxx-pkgs/runner/README.md

102 lines
3.5 KiB
Markdown

# cargoxx-pkgs runner
Self-hosted Gitea Actions runner that validates package PRs.
## Architecture
```
+----------------+ +-------------------+ +--------------------+
| Gitea instance | <----> | act_runner | -----> | job container |
| (queues jobs) | poll | (this docker- | docker| cargoxx-runner- |
| | | compose service) | spawn | job:latest |
+----------------+ +-------------------+ +--------------------+
```
- `compose.yml` runs the official `gitea/act_runner:nightly` image,
which polls Gitea for jobs and spawns one container per workflow
run via the host's Docker socket.
- `flake.nix` builds the **job container image** — reproducible,
declarative, ships `nix`, `git`, `curl`, `jq`, `tea`, and a
single-user `NIX_CONFIG`. This image runs the actual workflow
steps; act_runner just orchestrates it.
- `config.yaml` maps `runs-on: self-hosted` (from
`.gitea/workflows/*.yml`) to the job image.
## One-time setup
1. **Build + load the job image** into the host's Docker daemon:
```sh
cd runner
nix run --extra-experimental-features 'nix-command flakes' .#load-image
```
Re-run whenever you bump nixpkgs or change the tool list.
2. **Mint a runner registration token** in the Gitea UI:
`Site Administration → Actions → Runners → Create new Runner`.
Copy the token.
3. **Provision the `.env`** alongside `compose.yml`:
```env
GITEA_INSTANCE_URL=https://git.amadey.xyz
GITEA_RUNNER_REGISTRATION_TOKEN=<paste here>
GITEA_RUNNER_NAME=cargoxx-pkgs-runner
GITEA_RUNNER_LABELS=self-hosted
```
4. **Generate the binary-cache signing key** + cache directory. The
workflow's "push to binary cache" step writes here; nginx (or
anything you point at it) serves it back over HTTPS to consumers.
```sh
mkdir -p cache/store
nix-store --generate-binary-cache-key \
cache.cargoxx.<your-domain> \
cache/cache.sec cache/cache.pub
chmod 600 cache/cache.sec
```
The `cache/` directory is gitignored. Both keys live alongside
`compose.yml`; the named volume binds use `${PWD}/cache/...`.
5. **(optional) Front the store with Caddy** so substituters can read it.
A ready-to-edit `Caddyfile.example` ships in this directory — copy
into `/etc/caddy/Caddyfile` (or `import` it) and reload:
```sh
sudo install -m644 Caddyfile.example /etc/caddy/conf.d/cargoxx-cache
sudo systemctl reload caddy
```
Caddy auto-provisions a Let's Encrypt cert. Consumers later need
`substituters = https://cache.cargoxx.<your-domain>` and
`trusted-public-keys = <contents of cache.pub>` in their nix config
— those go into the cargoxx wrapper (`cargoxx`'s own `flake.nix`),
so any user installing the bundled cargoxx picks them up.
6. **Start the runner**:
```sh
docker compose up -d
docker compose logs -f runner
```
First boot registers the runner with Gitea; subsequent boots reuse
the persisted token in `./data/.runner`.
## Updating
- Change a workflow step's tools → edit `flake.nix`, rerun
`nix run .#load-image`.
- Bump nixpkgs → `nix flake update` in this dir, rebuild the image.
- act_runner itself updates by `docker compose pull && docker compose up -d`.
## Why not host mode?
Host mode (act_runner running workflows directly on the host) would
save the Docker indirection but tightly couples the runner host to
the toolchain. Docker mode lets us treat the job image as a
deployable artifact — same image on every runner, no drift.