All apps · 0 apps
CI Runner Farm
Plugin from Lime Technology
Overview
Point it at a repo or organization, paste a GitHub token, and your CI runs on your own hardware — as many jobs in parallel as your box can handle, with pnpm/npm/yarn/Playwright caches that stay hot between runs, at zero cost per minute. Everything is configured from a single webGUI page: store your token, Start/Stop/Restart/Scale, watch live status, and build your runner image.
Security: self-hosted runners execute arbitrary workflow code on your hardware, and DinD runners run privileged. Use them only for trusted/private repositories — never let public/fork-PR code run on a privileged self-hosted runner. The plugin actively warns you when a privileged runner is pointed at a public repo. See the README for full guidance.
Readme
View on GitHubCI Runner Farm for Unraid
Turn your Unraid server into a fleet of GitHub Actions self-hosted runners — multiple concurrent, resource-capped runners running as Docker containers, with warm shared caches, queue-aware autoscaling, and Docker-in-Docker. No VM required.
Hosted CI minutes are slow and metered. Meanwhile, the Unraid server in your rack has spare cores and a fast cache pool sitting idle between media tasks. Point CI Runner Farm at a repo or organization, paste a token, and your builds run on your own hardware — as many in parallel as your box can handle, with dependency caches that stay hot between runs, at zero cost per minute.
Why run your own CI?
- Cost. Hosted CI bills by the minute. A server you already own runs builds for the price of the electricity.
- Speed. Run many jobs in parallel and keep pnpm/npm/yarn/Playwright caches warm on a local NVMe pool — no re-downloading the world on every run.
- It's the Unraid thing to do. Self-hosted runners are just Docker containers, and Docker is what your server is already great at. This is "do more with the hardware you have," turned up to a build farm.
- A couple of clicks to install. It's a normal plugin from Community Applications, configured entirely from the webGUI.
What you get
| Capability | What it means |
|---|---|
| N concurrent runners | Each runner is its own container, optionally capped with --cpus / --memory so CI never starves the rest of the host. |
| Queue-aware autoscaling | An optional daemon floats the fleet between a min and max based on how many jobs are waiting — capacity when you need it, idle when you don't. |
| Warm shared caches | pnpm / npm / yarn / Playwright caches (fully configurable) live on a fast pool and are reused across every run. This is the biggest hidden speed win over hosted CI. |
| Docker-in-Docker per runner | Jobs that use services: or docker compose just work, with an optional shared pull-through registry mirror so images are pulled once for the whole fleet. |
| Bring your own image | Use the in-plugin image builder, or point at any image you publish to a registry (public or private). |
| One webGUI page | Configure everything, store your token securely, Start/Stop/Restart/Scale, watch live status, and build your runner image — no shell required. |
How it works
The plugin provisions a set of Docker containers from a runner image — built in-plugin or pulled from a registry. Each container registers itself with GitHub as a self-hosted runner, either at repo scope or org scope (org scope gives you one shared pool that any of your private repos can pull from).
Persistent package caches and the build workspace are bind-mounted from a fast pool so they survive across jobs. An optional companion container runs a pull-through registry mirror, so Docker-in-Docker jobs across the whole fleet pull each image only once. And an optional autoscaler watches the GitHub job queue, scaling the fleet up toward your max when work is waiting and back down to your min when things go quiet.
Install
Community Applications (recommended)
Search for CI Runner Farm in Community Applications and click Install.
Install by URL
In the Unraid webGUI go to Plugins → Install Plugin and paste:
https://github.com/unraid/ci-runner-farm/releases/latest/download/ci-runner-farm.plg
Unraid always resolves this to the newest published release, and its built-in "check for updates" keeps the plugin current.
Setup, step by step
You'll need a GitHub Personal Access Token and a fast pool/share for caches. Everything below happens on one page: Settings → Utilities → CI Runner Farm.
1. Point it at GitHub and size the fleet
Choose your scope (repo or org), set the owner and target repos, an
optional runner group, and how many concurrent runners to run. Add
runner labels (so workflows can target this fleet with runs-on:) and
optional CPU / memory caps per runner so CI can't starve the rest of the box.

2. Choose a runner image, caches, and Docker mode
The Image source selector decides where each runner's image comes from:
- Built-in (default) — run the image built by the in-plugin Runner image
builder, tagged
ci-runner-farm-runner:latest. The plugin ships a generic starterdefault.Dockerfile(stock runner base + a Docker-in-Docker readiness wrapper); customize it — add language runtimes, browsers, build tools — then Build and restart. No registry needed. - Remote — pull a named image, e.g.
ghcr.io/org/ci-runner-image:latest. For a private image, set the registry server and username and save a registry token; the host runsdocker loginbefore provisioning. Forghcr.io, leaving the registry token blank reuses your GitHub token (it just needsread:packages).
Below that, configure the warm caches (host-subdir → container-path mounts; defaults cover pnpm/npm/yarn/Playwright), the workspace root, and the Docker-in-Docker mode.

3. (Optional) Turn on queue-aware autoscaling
Set a min and max runner count, a warm idle buffer, an autoscale step, a demand check interval, and a scale-down grace period. The daemon adds runners when jobs are queued and removes idle ones once the grace window passes — so you keep capacity ready without leaving the whole fleet running around the clock.

4. Save your token, validate, and start the fleet
Save a GitHub Personal Access Token (repo scope; add admin:org for org
runners). It's stored at /boot/config/plugins/ci-runner-farm/token with
chmod 600 and is never written into your plugin config. Click Validate
(no token needed) to confirm the host can provision, then use the fleet
controls — Start / Stop / Restart / Scale — and watch live per-runner status
(state, phase, CPU, memory). The Runner image builder panel lets you edit
the Dockerfile and rebuild right from the page.

5. Confirm it's running
Once started, the runners show up as ordinary Docker containers
(ci-runner-1…N), plus the optional ci-runner-mirror registry mirror — each
with the warm-cache bind mounts you configured. Your runners register with
GitHub and start picking up jobs.

Security
Self-hosted runners execute arbitrary workflow code on your hardware. Read this before exposing the fleet:
- DinD runners run
--privileged, and the shared-socket mode gives runners root-equivalent access to the host. Use self-hosted runners only for trusted/private repositories. Fork-PR code from public repos must never run on a privileged or socket-mounted self-hosted runner. - The plugin actively warns you. When you Start the fleet (and live on the settings page), it checks each repo-scope target's visibility via your token and shows a prominent warning if any is public while runners are privileged. It warns rather than blocks — the call stays yours.
Share host docker.socknow defaults to off. Turn it on only for trusted private repos; DinD (the default) already coversservices:without it.- Your GitHub token never enters a runner container. The PAT stays on the host; each runner is handed only a short-lived registration token, and runners are deregistered host-side. So a workflow step can't read your token out of its own environment.
- Network isolation (Docker section) confines runners at the network layer:
isolateputs them on a dedicated bridge so they can't reach your other Unraid containers;strictadds firewall rules (Docker'sDOCKER-USERchain) that also block the runners from the Unraid host and your LAN, while still allowing the internet and the shared image cache. Recommended if runners might touch less-trusted code. Applies on the next Start; needsiptableson the host.
- For stronger isolation, set
EPHEMERAL=trueso each job gets a clean runner. - At org scope, create a runner group restricted to your private repos so a public repo can never schedule onto these runners.
See GitHub's self-hosted runner security guidance for the full picture.
CLI
Everything in the UI maps to the control script:
include/runner-farm.sh {start|boot-autostart|stop|restart|scale N|status|status-json|logs i|validate|build-image|prune-cache|autoscale-*}
Releases & versioning
Releases are automated with release-please and published as GitHub Release assets — the same flow used by Unraid's other plugins.
.release-please-manifest.jsonis the SemVer source of truth;VERSIONmirrors it for tooling.- Merging Conventional Commits to
mainopens a release PR. That PR regenerates the self-containedci-runner-farm.plg(version entities + embedded payload) and updatesCHANGELOG.md. - Merging the release PR tags
vX.Y.Z, cuts a GitHub Release, validates the tagged.plg, and uploads it as theci-runner-farm.plgrelease asset that the install URL above resolves to.
The Unraid plugin-manager <version> is written as
YYYY.MM.DD.HHMM.BUILD-INTERNAL (e.g. 2026.06.24.1530.42-0.1.0) so it sorts
chronologically in the plugin manager while still pinning the SemVer release.
Development
./build-plg.sh # build ci-runner-farm.plg from src/ (date-stamped dev build)
./deploy.sh root@tower # rsync src/ to a dev Unraid host (fast iteration; not for installs)
The .plg is fully self-contained: the plugin file tree is tarred,
base64-encoded, and embedded inline, so installing only ever fetches the single
.plg — no external file hosting.
Layout
ci-runner-farm.plg self-contained installer (built artifact, committed)
build-plg.sh packages src/ -> versioned .plg
deploy.sh dev-only raw deploy to an Unraid host
release-please-config.json release-please configuration
.release-please-manifest.json SemVer source of truth
VERSION mirror of the internal SemVer version
src/usr/local/emhttp/plugins/ci-runner-farm/
RunnerFarm.page Settings page (Dynamix)
default.cfg seed config
default.Dockerfile generic starter runner image
include/runner-farm.sh provisioning/control script
include/exec.php CSRF-guarded web endpoint
.github/workflows/
package-plugins.yml PR/branch build + validate
release-please.yml release automation + asset upload
release.yml tagged-release validation
Support
Questions and bug reports: https://github.com/unraid/ci-runner-farm/issues
Media gallery
Install CI Runner Farm on Unraid in a few clicks.
Find CI Runner Farm in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Requirements
⚠ Security — this plugin runs arbitrary CI code as root on your server.
CI Runner Farm executes GitHub Actions jobs in privileged Docker-in-Docker containers on this Unraid box. Any workflow scheduled onto the fleet — including a pull request from a fork of a public repo — runs with root-equivalent access to the host Docker daemon and to any shares you expose to it.
Only run trusted workflows on trusted runners. Point the fleet at private / trusted repositories only; never let public or fork-PR code run on a privileged self-hosted runner. At org scope, use a runner group restricted to your private repos. The plugin also warns you live in its settings page if it detects a public repo on a privileged fleet.
By installing you acknowledge these risks and accept responsibility for what runs on your fleet.
Download Statistics
Downloads by Month
Related apps
Explore more like this
Explore allDetails
https://github.com/unraid/ci-runner-farm/releases/latest/download/ci-runner-farm.plg