Self-Hosted Runners — Part 1: Try the Runner on Your Own Machine
Tutorial · Getting Started · written for the hub Tutorials category
Series: Part 1 — Local · Part 2 — CI · Part 3 — Your Computer
Hey! Want to see the Infinito.Nexus CI runner actually work — build an image and deploy a real app — without touching GitHub, a server, or anyone else’s stack? That’s what this guide does. By the end you’ll have run the runner’s full self-test on your own laptop, in a sealed sandbox that cleans up after itself.
First time here? Set up your machine first — see Part 3: Set Up Your Computer (or the full Installation Guide). This tutorial is only about the runner.
What does “test the runner locally” even mean?
The svc-runner role ships its own end-to-end test. When you deploy the role, test-e2e-cli notices it (it declares templates/test.env.j2) and runs files/test/test.sh, which does two things:
-
local.sh— runs entirely on your machine, no GitHub. ← this is the fun part -
external.sh— the GitHub job-pickup smoke test; skips automatically when there’s no token
So you can exercise basically everything locally.
What local.sh does, step by step
1. 🩺 checks the runner containers are healthy + the Docker socket works
2. 📦 container cp → copies this repo into runner-1
3. 🔨 make build → builds the Infinito image LOCALLY (no GHCR pull)
4. 📦 spins up a sealed, throwaway docker:dind sandbox
5. 🚀 deploys web-app-dashboard (everything else off) INSIDE that sandbox
6. 🧹 tears the sandbox down on exit — your real stack is never touched
No PAT, no GHCR login, no registration. Just your machine.
What you need
-
A working dev stack:
make install && make compose-up(see the install guide above) -
Docker with a reachable socket
-
Patience + disk: this is a real nested deploy — budget tens of GB and a long run
Run it
make compose-deploy apps=svc-runner
Watch it live in another terminal:
tail -f /tmp/ansible-runner-dind-test.log
You’re looking for, in order:
-
running full local deploy test inside …→ the sandbox deploy started -
the
web-app-dashboarddeploy finishing -
ALL LOCAL CHECKS PASSED (DinD)
“Why did it skip the big deploy the second time?”
Each app deploys twice (sync + async). The heavy nested deploy only runs on the sync pass; on the async pass you’ll see:
Skipping full deploy on async pass (validated on sync pass)
That’s on purpose — it roughly halves the runtime. ![]()
But how do I test other roles with it — like matomo?
Great question — because deploying apps is the runner’s actual job. The web-app-dashboard in local.sh is just the runner’s own smoke test (“can I build an image and deploy something?”). The real value is running a deploy-test for any app.
In CI
You don’t pick by hand — the matrix automatically routes a job per changed app to the runners. Touch web-app-matomo → a matomo deploy-test lands on a runner. Touch nextcloud → same. (See Part 2.)
Locally
Run the exact same sandboxed deploy-test for any role yourself:
make compose-deploy apps=web-app-matomo # deploy + test matomo
make compose-deploy apps=web-app-nextcloud # …or any role
make compose-deploy apps=web-app-matomo mode=reinstall full_cycle=true # full sync+async cycle
This is the same machinery each runner job uses — one app, in an isolated stack. So “using the runner to test matomo” locally = running matomo’s deploy-test this way.
In short: local.sh proves the runner works; make compose-deploy apps= is how you actually exercise other roles with the same mechanism.
Want to drive a runner (not your local stack) to deploy a role you pick — on demand? That’s the CI: Manual trigger with a
whitelist— see Part 2 → Manually pick which roles a runner deploys.
Working on the role?
make test # fast: lint + rule tests (catches most mistakes)
make compose-deploy apps=svc-runner # slow: the real end-to-end (sealed-sandbox deploy)
Heads up: make test does not run the nested deploy — that’s the compose-deploy line (and CI).
Next in the series
-
Part 2: Plug your runners into CI
-
Part 3: Set up your computer to work with it all
-
Deep reference: roles/svc-runner/README.md
Cheat sheet
make compose-up # dev stack up
make compose-deploy apps=svc-runner # runs local.sh (the sealed-sandbox test)
tail -f /tmp/ansible-runner-dind-test.log
# 🎉 success = “ALL LOCAL CHECKS PASSED (DinD)”