# Gitea Act Runner ## Overview Gitea Actions is Gitea's built-in CI/CD system, compatible with GitHub Actions workflows. The **Act Runner** is the agent that executes these workflows. It picks up jobs from a Gitea instance, spins up Docker containers for each workflow step, runs the commands, and reports results back. The name "act" comes from [nektos/act](https://github.com/nektos/act), an open-source tool originally built to run GitHub Actions locally. Gitea forked and adapted it into their runner, so `act_runner` is a lineage artifact — the binary keeps the upstream name, but everything else in our infrastructure uses `gitea-runner`. ### How it works 1. The runner daemon polls the Gitea instance for queued workflow jobs 2. When a job is picked up, the runner pulls the Docker image specified by the workflow label (e.g., `ubuntu-24.04` maps to `docker.gitea.com/runner-images:ubuntu-24.04`) 3. Each workflow step executes inside an ephemeral container 4. Logs and status are streamed back to Gitea in real time 5. The container is destroyed after the job completes ### Architecture in Agathos ``` Gitea (Rosalind) Act Runner (Puck) ┌──────────────┐ poll/report ┌──────────────────┐ │ gitea.ouranos │◄──────────────────│ act_runner daemon │ │ .helu.ca │ │ (gitea-runner) │ └──────────────┘ └────────┬─────────┘ │ spawns ┌────────▼─────────┐ │ Docker containers │ │ (workflow steps) │ └──────────────────┘ ``` ### Naming conventions The **binary** is `act_runner` — that's the upstream package name and renaming it would break updates. Everything else uses `gitea-runner`: | Component | Name | |-----------|------| | Binary | `/usr/local/bin/act_runner` (upstream, don't rename) | | Service account | `gitea-runner` | | Home directory | `/srv/gitea-runner/` | | Config file | `/srv/gitea-runner/config.yaml` | | Registration state | `/srv/gitea-runner/.runner` (created by registration) | | Systemd service | `gitea-runner.service` | | Runner name | `puck-runner` (shown in Gitea UI) | --- ## Ansible Deployment The runner is deployed via the `gitea_runner` Ansible service to **Puck** (application runtime host with Docker already available). ### Prerequisites - Docker must be installed on the target host (`docker` in services list) - Gitea must be running and accessible at `https://gitea.ouranos.helu.ca` ### Deploy ```bash # Deploy to all hosts with gitea_runner in their services list ansible-playbook gitea_runner/deploy.yml # Dry run (skip registration prompt) ansible-playbook gitea_runner/deploy.yml --check # Limit to a specific host ansible-playbook gitea_runner/deploy.yml --limit puck.incus # Non-interactive mode (for CI/CD) ansible-playbook gitea_runner/deploy.yml -e registration_token=YOUR_TOKEN ``` The playbook is also included in the full-stack deployment via `site.yml`, running after the Gitea playbook. **Registration Prompt**: On first deployment, the playbook will pause and prompt for a registration token. Get the token from `https://gitea.ouranos.helu.ca/-/admin/runners` before running the playbook. ### What the playbook does 1. Filters hosts — only runs on hosts with `gitea_runner` in their `services` list 2. Creates `gitea-runner` system group and user (added to `docker` group) 3. Downloads `act_runner` binary from Gitea releases (version pinned as `act_runner_version` in `group_vars/all/vars.yml`) 4. Skips download if the installed version already matches (idempotent) 5. Copies the managed `config.yaml` from the Ansible controller (edit `ansible/gitea_runner/config.yaml` to change runner settings) 6. Templates `gitea-runner.service` systemd unit 7. **Registers the runner** — prompts for registration token on first deployment 8. Enables and starts the service ### Systemd unit ```ini # /etc/systemd/system/gitea-runner.service [Unit] Description=Gitea Runner After=network.target docker.service Requires=docker.service [Service] Type=simple User=gitea-runner Group=gitea-runner WorkingDirectory=/srv/gitea-runner ExecStart=/usr/local/bin/act_runner daemon --config /srv/gitea-runner/config.yaml Restart=on-failure RestartSec=10 Environment=HOME=/srv/gitea-runner [Install] WantedBy=multi-user.target ``` ### Registration Flow On first deployment, the playbook will automatically prompt for a registration token: ``` TASK [Prompt for registration token] Gitea runner registration required. Get token from: https://gitea.ouranos.helu.ca/-/admin/runners Enter registration token: [Enter token here] ``` **Steps**: 1. Before running the playbook, obtain a registration token: - Navigate to `https://gitea.ouranos.helu.ca/-/admin/runners` - Click "Create new Runner" - Copy the displayed token 2. Run the deployment playbook 3. Paste the token when prompted The registration is **idempotent** — if the runner is already registered (`.runner` file exists), the prompt is skipped. **Non-interactive mode**: Pass the token as an extra variable: ```bash ansible-playbook gitea_runner/deploy.yml -e registration_token=YOUR_TOKEN ``` **Manual registration** (if needed): The traditional method still works if you prefer manual control. Labels are picked up from `config.yaml` at daemon start, so `--labels` is not needed at registration: ```bash ssh puck.incus sudo -iu gitea-runner act_runner register \ --instance https://gitea.ouranos.helu.ca \ --token \ --name puck-runner \ --no-interactive ``` ### Verify ```bash # Check service status sudo systemctl status gitea-runner # Check runner version act_runner --version # View runner logs sudo journalctl -u gitea-runner -f ``` `puck-runner` should show as **online** at `https://gitea.ouranos.helu.ca/-/admin/runners`. ### Runner labels Labels map workflow `runs-on` values to Docker images. They are configured in `ansible/gitea_runner/config.yaml` under `runner.labels`: | Label | Docker Image | Use case | |-------|-------------|----------| | `ubuntu-latest` | `docker.gitea.com/runner-images:ubuntu-latest` | General CI (Gitea official image) | | `ubuntu-24.04` | `docker.gitea.com/runner-images:ubuntu-24.04` | Ubuntu 24.04 builds | | `ubuntu-22.04` | `docker.gitea.com/runner-images:ubuntu-22.04` | Ubuntu 22.04 builds | | `ubuntu-20.04` | `docker.gitea.com/runner-images:ubuntu-20.04` | Ubuntu 20.04 builds | | `node-24` | `node:24-bookworm` | Node.js CI | To add or change labels, edit `ansible/gitea_runner/config.yaml` and re-run the playbook. ### Configuration reference | Variable | Location | Value | |----------|----------|-------| | `act_runner_version` | `group_vars/all/vars.yml` | `0.2.13` | | `gitea_runner_instance_url` | `group_vars/all/vars.yml` | `https://gitea.ouranos.helu.ca` | | `gitea_runner_name` | `host_vars/puck.incus.yml` | `puck-runner` | | Runner labels | `ansible/gitea_runner/config.yaml` | See `runner.labels` section | ### Upgrading To upgrade the runner binary, update `act_runner_version` in `group_vars/all/vars.yml` and re-run the playbook: ```bash # Edit the version vim inventory/group_vars/all/vars.yml # act_runner_version: "0.2.14" # Re-deploy — only the binary download and service restart will trigger ansible-playbook gitea_runner/deploy.yml ```