2026-06-20 11:06:27 +07:00
|
|
|
# GitHub Actions self-hosted runners — Ansible
|
|
|
|
|
|
|
|
|
|
Provisions self-hosted runners 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, 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 runner version + sha256, paths, env_file
|
|
|
|
|
host_vars/<host>.yml runner_env + per-project `runners` matrix
|
|
|
|
|
tasks/install_project.yml reads token, expands count -> N instances
|
|
|
|
|
tasks/install_one_runner.yml download/verify/extract/register/service one runner
|
|
|
|
|
install-runner.yml the playbook
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Runner naming
|
|
|
|
|
|
|
|
|
|
- name: `<host>-<project>-<env>-<N>` e.g. `stage01-gatehouse-api-stage-1`
|
|
|
|
|
- dir: `/home/github-runner/actions-runner-<project>-<N>`
|
|
|
|
|
- label: `project_spec.label` (e.g. `stage-secuird-runner`, `stage-gatehouse-ui`)
|
|
|
|
|
- service: `actions.runner.<owner>-<repo>.<name>.service`
|
|
|
|
|
|
|
|
|
|
## Tokens
|
|
|
|
|
|
2026-06-20 11:24:27 +07:00
|
|
|
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`.
|
2026-06-20 11:06:27 +07:00
|
|
|
|
|
|
|
|
Mint each from the repo's **Settings > Actions > Runners > New self-hosted runner**
|
|
|
|
|
(the value after `--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.
|
2026-06-20 11:24:27 +07:00
|
|
|
# 2. Export fresh tokens (leading space keeps them out of shell history):
|
|
|
|
|
export RUNNER_TOKEN_GATEHOUSE_API=xxx
|
|
|
|
|
export RUNNER_TOKEN_GATEHOUSE_UI=yyy
|
2026-06-20 11:06:27 +07:00
|
|
|
|
|
|
|
|
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 'actions.runner.*'
|
|
|
|
|
ls /home/github-runner/ # actions-runner-gatehouse-api-1, -2, ...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Each repo's Settings > Actions > Runners should list the runners as **Idle** with the
|
|
|
|
|
expected label. Idempotent: re-running skips already-configured runners (`--replace`
|
|
|
|
|
re-registers safely; `creates:` guards downloads/extract/config).
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
|
|
|
|
|
- Bump `runner_version` + `runner_sha256` together in `group_vars/all.yml`
|
|
|
|
|
(sha256 from the GitHub release page).
|
|
|
|
|
- `deploy/deploy.sh` needs the runner user to have passwordless sudo for nginx reload —
|
|
|
|
|
add that sudoers drop-in separately (not yet automated here).
|
|
|
|
|
- `gatehouse-ui` repo URL + label in host_vars are placeholders — confirm before first run.
|