# Gitea Actions self-hosted runners — Ansible Provisions `act_runner` instances as **systemd services**. One host can run runners for multiple projects (e.g. `gatehouse-api` + `gatehouse-ui`); each project gets its own runner name, install dir, label set, repo URL, and registration token. ## Layout ``` ansible.cfg inventory + ssh defaults inventory.ini stage / prod host groups (set ansible_host) group_vars/all.yml pinned act_runner version + sha256, gitea_instance URL host_vars/.yml runner_env + per-project `runners` matrix tasks/install_project.yml reads token, expands count -> N instances tasks/install_one_runner.yml download/register/service one runner install-runner.yml the playbook ``` ## Runner naming - name: `---` e.g. `stage01-gatehouse-api-stage-1` - dir: `/home/gitea-runner/act-runner--` - labels: `project_spec.labels` (comma-separated, e.g. `self-hosted,linux,stage`) - service: `gitea-runner--.service` ## Before first run — pin act_runner version 1. Check [act_runner releases](https://gitea.com/gitea/act_runner/releases) for the latest stable version. 2. Download `act_runner--linux-amd64.sha256` from the release page. 3. Update `act_runner_version` and `act_runner_sha256` in `group_vars/all.yml`. ## Tokens Registration tokens are **per-repo and expire ~1h after minting**. Exported as env vars on the control node, named by each project's `token_env` in `host_vars`. Mint each from the repo's **Settings → Actions → Runners → Create new runner token**, then run the playbook within the hour. ## Run ```bash cd deploy/ansible # 1. Edit inventory.ini (set ansible_host / ansible_user) and host_vars/*.yml. # 2. Fill in act_runner_version + act_runner_sha256 in group_vars/all.yml. # 3. Export fresh tokens (leading space keeps them out of shell history): export RUNNER_TOKEN_GATEHOUSE_API=xxx export RUNNER_TOKEN_GATEHOUSE_UI=yyy ansible-playbook --syntax-check install-runner.yml ansible-playbook install-runner.yml --check --diff --limit stage # dry run ansible-playbook install-runner.yml --limit stage # apply ``` ## Verify ```bash # on the host systemctl list-units 'gitea-runner-*' ls /home/gitea-runner/ # act-runner-gatehouse-api-1, ... ``` Each repo's **Settings → Actions → Runners** should list the runners as **Idle** with the expected labels. Idempotent: re-running skips already-registered runners (`creates: .runner` guards re-registration; binary download is checksum-gated). ## Migrating from GitHub Actions runners Stop and remove the old runners on any existing host before re-running: ```bash sudo su - github-runner -c "cd ~/actions-runner-*/; ./svc.sh stop && ./svc.sh uninstall" sudo userdel -r github-runner # optional — removes home dir too ``` ## Notes - Bump `act_runner_version` + `act_runner_sha256` together in `group_vars/all.yml`. - Labels in `host_vars/.yml` must match the `runs-on:` values in workflow files. - `deploy/deploy.sh` needs the runner user to have passwordless sudo for nginx reload — add that sudoers drop-in separately (not yet automated here). Update the username from `github-runner` to `gitea-runner` in that drop-in. - `prod01.ansible_host` in `inventory.ini` is still `CHANGE_ME` — fill in before running prod.