-
Notifications
You must be signed in to change notification settings - Fork 0
Home

Ephemeral Action Runner (EPAR) keeps a warm pool of disposable GitHub Actions self-hosted runners on your own machine.
Each runner is made for one job. EPAR starts it, registers it with GitHub, lets one workflow job run, deletes it, and creates a fresh replacement.
flowchart TB
EPAR["EPAR"] --> Create["Create runner"]
Create --> Ready["Runner ready"]
Ready --> Job["Run one GitHub Actions job"]
Job --> Delete["Delete runner"]
Delete --> Create
Private repositories often have limited GitHub-hosted Actions minutes. If you already have a spare Windows, macOS, Linux, or Docker-capable machine, you can use it for feature-branch CI instead of spending those hosted-runner minutes.
A normal long-lived self-hosted runner can leave dependencies, files, containers, caches, or other job state behind on that machine. EPAR lowers that risk by running each job in a disposable container, WSL distro, or VM, then deleting it and creating a clean replacement.
- Warm pool: keep ready self-hosted runners online after setup.
- Disposable jobs: each runner is cleaned up after one job.
- Great default image: Docker-DinD and WSL use Gitea's full Ubuntu runner image by default.
- Docker-friendly isolation: Docker-DinD gives each runner its own private Docker daemon.
- Simple host use: run Linux GitHub Actions jobs from a Windows, macOS, Linux, or Docker-capable host.
The easiest path is the default Docker-DinD mode. It works well for most Linux GitHub Actions jobs, especially Docker and Docker Compose jobs.
Make sure these are installed:
- Go 1.22 or newer
- a Docker-compatible daemon:
- Windows: Docker Desktop, or another Docker daemon reachable from PowerShell
- macOS: Docker Desktop or OrbStack
- Linux: Docker Engine
The default Docker-DinD mode uses docker run --privileged, so the daemon must support privileged Linux containers.
Open the EPAR GitHub repo, choose Code, then Download ZIP.
Extract the ZIP and open a terminal in the extracted folder. The folder is usually named ephemeral-action-runner-main.
cd path/to/ephemeral-action-runner-mainEPAR uses a GitHub App to create short-lived runner registration tokens.
Follow GitHub App Setup, then keep these three values ready:
- GitHub App ID
- GitHub organization name
- private key file path
Run EPAR with the default flow:
go run ./cmd/ephemeral-action-runnerThat's it.
EPAR initializes .local/config.yml for you if it does not exist. You can customize the config afterward; see Configuration.
Then EPAR checks the configured runner image, builds or replaces it when needed, and starts the configured number of runners. The default config uses pool.instances: 1.
The first run can take a while because EPAR may need to build the runner image before it starts the pool. Later runs reuse the aligned image unless the config, EPAR scripts, or source image changed.
Keep EPAR running while you want runners online. Stop with Ctrl-C; EPAR cleans up matching local instances and GitHub runner records by default.
To choose a config or runner count:
go run ./cmd/ephemeral-action-runner start --config .local\wsl.yml --instances 2If --instances is omitted, EPAR uses pool.instances from the config.
GitHub Actions picks a runner by matching the job's runs-on list with the labels registered on each runner. Every self-hosted runner gets the self-hosted label, so the simplest workflow can use:
runs-on: [self-hosted]If you have multiple self-hosted runners and want this job to run on a specific kind of EPAR runner, add one of its extra labels to the list, e.g.:
runs-on: [self-hosted, epar-docker-dind-gitea-ubuntu]EPAR also adds an epar-host-<machine> label by default, so you can see which host registered each runner. You only need to include that label in runs-on when you intentionally want a job to target one machine.
Docker-DinD is the default first choice. Other providers are available when they fit your host better:
| Provider | Use when |
|---|---|
| Docker-DinD | You have a Docker-compatible daemon on Windows, macOS, or Linux, and want a private Docker daemon per runner. |
| WSL2 | You are on Windows and want runners as disposable WSL distros. |
| Tart | You are on Apple Silicon macOS and want Linux VM runners; consider Docker-DinD first for Docker-heavy jobs because virtualization limits can affect compatibility. |
WSL2 also defaults to Gitea's full Ubuntu runner image, but it converts that Docker image into a WSL rootfs during image build.
See Usage for WSL, Tart, source builds, custom configs, and advanced options.
Yes. Set pool.instances in .local/config.yml, or pass --instances N for one run.
Yes. Use one config per organization, then start EPAR once per config. Each config should use its own GitHub App values and a distinct pool.namePrefix.
Yes. EPAR registers disposable ephemeral runners. After a job finishes, EPAR deletes that runner and creates a replacement.
Yes, with the default Docker-DinD mode. Each runner gets its own private Docker daemon, so job-created containers, networks, and volumes stay inside that disposable runner.
EPAR is for trusted jobs. It improves cleanup and reduces stale runner state, but it does not make your machine safe for arbitrary untrusted code.
GitHub also warns against using self-hosted runners with public repositories that can run untrusted pull request workflows. Read GitHub's self-hosted runner guidance before exposing a runner to untrusted users.
- Usage: setup, image builds, verification, and pool commands.
- Configuration: config file sections and common edits.
- GitHub App Setup: required GitHub App permissions and fields.
- Docker-DinD Provider: default Docker runner mode.
- WSL Provider: Windows WSL2 runners.
- Tart Provider: Apple Silicon Linux VM runners.
- Image Build: image internals and customization.
- Operations: logs, cleanup, and troubleshooting.
- Windows Startup: start EPAR after Windows login.
- macOS Startup: start EPAR after macOS login.
- Security: trust boundaries and secret handling.
Generated from the main repository docs at e3c8302. Edit README.md and docs/; the wiki copy is overwritten by automation.