Self-Hosted Runners — Part 2: Plug Them into CI
Tutorial · Getting Started · written for the hub Tutorials category
Series: Part 1 — Local · Part 2 — CI · Part 3 — Your Computer
So you’ve got runners ready (your machine set up + a box provisioned in Part 3). This guide shows how to make GitHub Actions actually send your CI deploy jobs to them — and how to turn that off in one command when you need to.
Want the big-picture overview of the whole test pipeline? See docs/administration/ci-runners.md.
The one knob you need to know
GitHub-hosted runners are the default — out of the box, everything runs on GitHub’s machines. Self-hosted runners are opt-in overflow, controlled by a single repository variable:
CI_SELF_HOSTED_RUNNER_COUNT |
What happens |
|---|---|
0 / unset |
|
N |
[self-hosted, linux] runners |
That’s it. One variable flips the whole thing.
Turn it on
From your control machine:
make runner-ci-enable COUNT=2
# on a fork:
make runner-ci-enable COUNT=2 OWNER=youruser
This sets two repo variables for you:
-
CI_SELF_HOSTED_RUNNER_COUNT = COUNT→ activates the split -
INFINITO_TIMEOUT_MULTIPLIER = 30→ gives slower self-hosted hardware more breathing room (~1 h max wait)
Check it landed:
github.com/<owner>/infinito-nexus/settings/variables/actions
Now push any commit — deploy jobs fan out across GitHub-hosted and your runners. ![]()
Turn it off (the panic button)
Machine down? Acting weird? One command sends everything back to GitHub:
make runner-ci-disable
# fork:
make runner-ci-disable OWNER=youruser
Nothing blocks — CI just reverts to GitHub-hosted instantly.
What happens when a job lands on your runner
GitHub dispatches a deploy job to [self-hosted, linux]
│
▼
🏃 runner container (DooD — mounts the host docker socket)
│ builds the Infinito image locally, then…
▼
📦 sealed throwaway docker daemon → deploys the app + runs Playwright/CLI tests
│
▼
🧹 torn down on exit (host untouched)
Each runner instance is isolated (its own subnet, project name, volumes — keyed on the instance number), so several runners on one box happily run different apps in parallel without stepping on each other.
Manually pick which roles a runner deploys
You don’t have to wait for a code change — there’s a manual trigger that lets you hand-pick the app(s) to deploy on a runner:
GitHub UI
Actions →
CI: Manual → Run workflow →
-
whitelist= the app ids you want, space-separated → e.g.web-app-matomo(orweb-app-matomo web-app-nextcloud) -
distros= e.g.debian
From your computer
gh workflow run entry-manual.yml --repo <owner>/infinito-nexus \
-f distros="debian" \
-f whitelist="web-app-matomo"
whitelist values:
-
explicit app ids → just those
-
__ALL__→ everything -
empty → diff vs
main
With runners enabled (make runner-ci-enable), those jobs land on your runners, each deploying your chosen role in its isolated sandbox. This is how you drive a runner on demand — not just let CI feed it automatically.
Good to know: when does the runner’s own test run?
-
The matrix only includes apps that changed (diff vs
main). So svc-runner’s heavy local test fires only on PRs that touch svc-runner — not every run.
-
If svc-runner is changed and you have no self-hosted runners (
COUNT=0), it doesn’t get skipped — it falls back to GitHub-hosted and runs there (local.shruns; the GitHub-registration smoke testexternal.shskips, since there’s no token). Exactly what you want for validating the role.
Next / previous
-
Part 3: Set up your computer to work with it all
-
Part 1: Try the runner locally
Cheat sheet
make runner-ci-enable COUNT=2 [OWNER=youruser] # 🟢 on
make runner-ci-disable [OWNER=youruser] # 🔴 off
# check:
github.com/<owner>/infinito-nexus/settings/variables/actions