Self-Hosted Runners — Part 3: Turn a Computer into a Runner Host
Tutorial · Getting Started · written for the hub Tutorials category
Series: Part 1 — Local · Part 2 — CI · Part 3 — The Computer
Got a spare box, an old workstation, or a VM gathering dust? Let’s turn that computer into Infinito.Nexus CI runners so it picks up real deploy jobs from GitHub. You drive the whole thing from your laptop over SSH — you never log into the runner box directly. ![]()
This is the dedicated runner machine guide. For setting up your own dev machine, that’s Part 1. For deploy basics, see the Deploy Guide.
What you’re building
The svc-runner role drops N ephemeral runner containers onto one host. Each is a GitHub Actions self-hosted runner; when it gets a job it builds the Infinito image and runs a full app deploy + tests in an isolated sandbox, then re-registers fresh for the next job.
🖥️ the runner computer
├─ runner-1 (subnet 172.30.1.x, project runner-1) ┐
├─ runner-2 (subnet 172.30.2.x, project runner-2) ├─ each runs ONE job at a time,
└─ runner-N (subnet 172.30.N.x, project runner-N) ┘ fully isolated from the others
What you need
On your control machine
(your laptop — the one set up in Part 1)
-
A checkout with
make installdone -
A GitHub Personal Access Token (reposcope) asRUNNER_API_TOKEN(orGH_TOKEN) -
ghCLI logged in, and SSH key access to the runner box
On the runner computer
-
Clean Linux — Debian, Ubuntu, Arch, or Fedora/CentOS -
Docker with a reachable socket -
Disk for image builds — budget tens of GB
The runner box can even be the same machine you work on — it just needs Docker + SSH.
Step 1 — Provision
One command, from your control machine:
RUNNER_API_TOKEN=ghp_... make runner-ci-deploy HOST=runner.example.com DISTRO=ubuntu
On a fork, add your username so runners register against your repo (never upstream):
RUNNER_API_TOKEN=ghp_... make runner-ci-deploy HOST=runner.example.com DISTRO=ubuntu OWNER=youruser
Follow the live log in another terminal:
tail -f /tmp/infinito-runner-deploy.log
| Parameter | Default | Notes |
|---|---|---|
HOST |
— (required) | hostname/IP of the runner box |
DISTRO |
— (required) | debian / ubuntu / archlinux / fedora / centos |
COUNT |
15 (CLI auto = vCPUs ÷ 2) |
number of runner instances |
PORT |
22 | SSH port |
OWNER |
infinito-nexus |
GitHub user/org to register with |
REPO |
core |
repository to register with |
Step 2 — Verify they showed up
gh api repos/youruser/infinito-nexus/actions/runners -q '.runners[].name'
They should appear as Idle
at:
github.com/<owner>/infinito-nexus/settings/actions/runners
Step 3 — Switch CI over to them
(That’s Part 2 — short version:)
make runner-ci-enable COUNT=2 [OWNER=youruser] # 🟢 activate
make runner-ci-disable [OWNER=youruser] # 🔴 panic button
Push a commit → jobs targeting [self-hosted, linux] now land on your box. ![]()
Why it’s safe to run (the isolation story)
-
DooD: runner containers mount the host Docker socket; jobs run on the host engine, namespaced per instance.
-
Per-instance everything: subnet
172.30.<N>.0/24, compose projectrunner-<N>, own volume dir, own registration. Keyed on instance number → parallel jobs cannot collide. -
Ephemeral: one job per instance, then re-register fresh.
-
Sandboxed deploys: each app deploy runs in a sealed throwaway daemon, torn down after — the host’s own stack is never touched.
So you can run these on a shared machine without fear of them stepping on each other or other workloads. ![]()
Bonus: reuse it for other projects
The runner image bakes only a toolchain (no Infinito code) — point it at a different repo by re-running runner-ci-deploy with another OWNER/REPO. A provider: gitea flavor (register against a self-hosted Gitea instead of GitHub) is on the roadmap — ticket #585. ![]()
The rest of the series
-
Part 1: Try the runner on your own machine
-
Part 2: Plug runners into CI
-
Deep reference: roles/svc-runner/README.md
Cheat sheet
RUNNER_API_TOKEN=ghp_... make runner-ci-deploy HOST=<host> DISTRO=ubuntu [OWNER=youruser]
tail -f /tmp/infinito-runner-deploy.log
gh api repos/<owner>/infinito-nexus/actions/runners -q '.runners[].name' # expect 🟢 Idle
make runner-ci-enable COUNT=2 [OWNER=youruser]
make runner-ci-disable [OWNER=youruser]