Self-hosting a GitHub Actions runner starts with a fairly simple goal: run your builds on your own hardware.
Then come the operational questions. Which runners are busy? Why is that job waiting? How do you add another machine? What did the previous build leave behind? And how much work will it take to move your existing repositories over?
I'm building Zoomies to make that experience easier.
It's a free, open-source GitHub Actions runner fleet controller with ephemeral runners, autoscaling across your own hosts, a live web UI, and a migration wizard that opens reviewable pull requests.
It runs as a single Go binary with SQLite. You don't need Kubernetes or a separate database server.
And yes, the name comes from dogs getting the zoomies. The cocker spaniel and the swishing paw print are very much part of the project. CI tools are allowed a little personality. 🐾
The real Zoomies interface, populated with the project's demo fleet. Screenshots throughout this article use demo data; the displayed timings are examples, not benchmarks.
Give each job a fresh runner
A long-lived runner gradually becomes a machine with history: checked-out repositories, installed tools, temporary files and whatever yesterday's workflow left behind.
Zoomies defaults to one job per runner. For container-backed pools, it starts a fresh runner container and removes it after the job finishes.
The controller watches GitHub's workflow_job webhooks, decides when more runners are needed, and asks an agent to start them on a matching host. Polling provides a fallback if webhook delivery isn't available.
You configure pools with the labels and capacity limits your workloads need. Zoomies scales the runners within those limits and the capacity of the hosts you've connected.
That last distinction matters: Zoomies manages runner capacity on your hosts. You still choose and provide the machines.
A web UI for the questions you actually ask
The web UI is a central part of Zoomies.
The Overview brings together queue depth, active jobs, runner counts, startup and registration timings, pool utilisation, and recent scaling decisions. Those decisions include explanations, so you can see why the fleet changed.
From there, you can inspect pools, runners, jobs and hosts, check usage, or follow the audit trail. Pages update through the controller's event stream, with light and dark themes and a command palette for getting around quickly.
When a job fails, its details show the failing step and timings, with a link to the relevant output on GitHub.
Job details connect a failed build to its runner, pool, timings and GitHub logs.
For terminal workflows, there's also a CLI and REST API. Prometheus metrics and structured logs let Zoomies fit into existing monitoring.
Multiple hosts, architectures and runner images
You can start with one machine and an embedded agent, then add remote agents as your needs grow.
The Hosts page shows health, available runner slots and detected backends. Its Add a host flow generates the command to enrol another machine using a single-use join token.
Agents initiate their connections to the controller, which is useful for machines behind NAT: you don't need an inbound connection to each agent.
See which machines have room for more runners and which need attention.
The runner image catalogue includes:
| Runner environment | Architectures |
|---|---|
| Ubuntu 24.04 | x86-64 and arm64 |
| Ubuntu 22.04 | x86-64 |
| Debian 12 | x86-64 and arm64 |
| Fedora 42 | x86-64 and arm64 |
| Rocky Linux 9 | x86-64 and arm64 |
Docker and Podman backends are available, alongside a process backend for running directly on a host. The controller and agents target Linux; macOS controller builds are intended for development. Windows runners and macOS runner images aren't currently supported.
See the platform details and support matrix for the distinction between available builds and runtime qualification.
Installation starts with one command
The installer is available at:
curl -fsSL https://zoomies.sh/install.sh | sh
It checks the host and guides you through the deployment choices, configuration and GitHub App connection. Native, Docker Compose and single-container deployment paths are available; the setup finishes in the terminal or browser depending on the path you choose.
The quick start also explains how to download and inspect the script before running it.
Once you've connected GitHub and created a pool, route a job to that pool's label. For example, a pool configured with zoomies-linux-x64 can receive jobs using:
runs-on: zoomies-linux-x64
Your workflow still runs through GitHub Actions. The runner environment needs the tools your steps depend on, so choose an appropriate image and try a representative build first.
Migration is built into the product
Getting a fleet running is only part of adoption. Moving repositories onto it is the next part.
Zoomies includes a Migrate wizard that reads the workflows your GitHub App can access, maps supported hosted-runner labels to your pools, and shows the proposed changes before opening a pull request for each selected repository.
A typical change looks like this:
- runs-on: ubuntu-latest
+ runs-on: zoomies-linux-x64
The wizard changes the selected runs-on values while preserving the surrounding formatting. It reports skipped jobs and their reasons, including matrix expressions and workflows already targeting self-hosted runners.
Review the exact workflow change before opening a PR. This demo also shows how missing GitHub App permissions are explained.
For teams already using static self-hosted runners, there's another route: configure a Zoomies pool to match the labels those workflows already request. Where the labels and environment are compatible, workflows can move across without editing their YAML, and you can retire the old runners gradually.
The migration guide covers both approaches.
Free software, infrastructure you control
Zoomies is released under AGPL-3.0. The source is available at eyupio/zoomies.
The software is free; you provide the compute, storage and network resources. Whether self-hosting saves money depends on your hardware, workload and operating costs.
Zoomies is currently an early beta, intended initially for workloads you trust. Its defaults include ephemeral runners, authentication, and container jobs without access to the host Docker socket. Self-hosted jobs still execute repository code, so read the security guide when choosing how to deploy it.
Give your CI the Zoomies
If you've been looking for a way to manage self-hosted GitHub Actions runners from a usable web interface, try Zoomies with one repository and one pool.
- Explore the project: zoomies.sh
- Get running: Quick start
- See more screenshots: Web UI tour
- Star, contribute or report an issue: eyupio/zoomies on GitHub
I'd love feedback from people running CI on their own machines: what's the biggest headache in your current runner setup?




Top comments (0)