Back to Dashboard

github-runner

2.337.0

Trust posture

๐Ÿ“‹ SBOM ATTESTED๐Ÿ›ก TRIVY: 2 CRITICAL (advisory) ยท SCANNED 2026-08-29๐Ÿ— AMD64 + ARM64 ๐Ÿ”— 3/3 deps tracked daily ๐Ÿ” REPRODUCE THESE CHECKS LOCALLY
PULLS 94.2K 59457 to 94233 pulls across 30 recorded days 2026-08-02: 59457 pulls2026-08-03: 59459 pulls2026-08-04: 59728 pulls2026-08-05: 60905 pulls2026-08-06: 62087 pulls2026-08-07: 62420 pulls2026-08-08: 63228 pulls2026-08-09: 63247 pulls2026-08-10: 64067 pulls2026-08-11: 64079 pulls2026-08-12: 64440 pulls2026-08-13: 66059 pulls2026-08-14: 66585 pulls2026-08-15: 66633 pulls2026-08-16: 69198 pulls2026-08-17: 69640 pulls2026-08-18: 69666 pulls2026-08-19: 71205 pulls2026-08-20: 71227 pulls2026-08-21: 72640 pulls2026-08-22: 75890 pulls2026-08-23: 77429 pulls2026-08-24: 77434 pulls2026-08-25: 77434 pulls2026-08-26: 78605 pulls2026-08-27: 79806 pulls2026-08-28: 83169 pulls2026-08-30: 93949 pulls2026-08-31: 94231 pulls2026-09-01: 94233 pulls
STARS 0
COVERAGE 18 variants ยท 3 versions ยท amd64+arm64

VERIFIABLE TRUST ARTIFACTS

Provenance

Build commit
8a8b07b
Build digest
sha256:8362b493712be949a76f90b50086b2d2ef5d3c21bd04e0081615fe918b74f21a
Index digest
sha256:f2f8cbf96107fadedc63668cb1db596959f2fe97f751c7bffe30d51622d575e8
Manifest digest (amd64)
sha256:d6bfe817534b6d074f1356c91122867602c17312a030727d980f3d5f20de1817
Manifest digest (arm64)
sha256:3113a3ff410127256558d9ad6781ab7d383291570745f69ef6a3ab0adff1ff32
SBOM attestation
43788957โ€ฆ
Trivy last scan
2026-08-29 00:48 UTC
Base image
Verify
gh attestation verify oci://ghcr.io/oorabona/github-runner:2.337.0 --owner oorabona guide โ†’

Security scan results

Trivy ยท last scan 2026-08-29

Last scan: (advisory mode โ€” Trivy runs continue-on-error in CI; we surface findings, we do not block builds on them).

2Critical
26High
40Medium
11Low
0Info

Top advisories (upstream, advisory)

  • CVE-2026-44777 (WARNING) โ€” github-runner โ€” jq: stack overflow in module loading on mutual include
  • CVE-2026-43896 (WARNING) โ€” github-runner โ€” jq: stack overflow in recursive object merge
  • CVE-2026-43895 (WARNING) โ€” github-runner โ€” jq: embedded NUL in jq import paths causes local redaction-policy bypass and preserves sensitive fields in published artifacts
  • CVE-2026-41257 (WARNING) โ€” github-runner โ€” jq: signed-int overflow in stack_reallocate
  • CVE-2026-41256 (WARNING) โ€” github-runner โ€” jq: embedded NUL truncates top-level jq programs loaded with -f

โ†’ Full report via gh api โ€” see Verify Images.

Explore

Available variants

TagSize (amd64) Build statusVersion
2.337.0 default545.8MB OK2.337.0
2.337.0-dev835.3MB OK2.337.0
2.337.0-debian-trixie584.8MB OK2.337.0
2.337.0-debian-trixie-dev968.3MB OK2.337.0
2.337.0-windows-ltsc20222666.2MB OK2.337.0
2.337.0-windows-ltsc2022-dev8549.7MB OK2.337.0
2.336.0 default290.1MB OK2.336.0
2.336.0-dev577.4MB OK2.336.0
2.336.0-debian-trixie349.6MB OK2.336.0
2.336.0-debian-trixie-dev730.8MB OK2.336.0
2.336.0-windows-ltsc20222665.7MB OK2.336.0
2.336.0-windows-ltsc2022-dev8549.2MB OK2.336.0
2.335.1 default289.8MB OK2.335.1
2.335.1-dev577.1MB OK2.335.1
2.335.1-debian-trixie349.3MB OK2.335.1
2.335.1-debian-trixie-dev730.4MB OK2.335.1
2.335.1-windows-ltsc20222662.1MB OK2.335.1
2.335.1-windows-ltsc2022-dev8546.0MB OK2.335.1
Build lineagesha256:
Build Lineage
Build Digest sha256:8362b493712be949a76f90b50086b2d2ef5d3c21bd04e0081615fe918b74f21a
Base Image
UBUNTU_2404_BASE ubuntu:24.04
DEBIAN_TRIXIE_BASE ghcr.io/oorabona/debian:trixie
PWSH_VERSION 7.6.5
GIT_VERSION 2.55.0.windows.5
JQ_VERSION 1.8.2
Package summary n/a โ€” runtime parsed
Recent changes n/a โ€” runtime parsed
Build history n/a โ€” runtime fetched
Dependency health all up to date

Dependency Health

all up to date
3/3 dependencies monitored
Up-to-date dependencies
PWSH_VERSION 7.6.5 GIT_VERSION 2.55.0.windows.5 JQ_VERSION 1.8.2

Documentation

README

github-runner

Self-hosted GitHub Actions runner in a Docker container. Supports Linux (Ubuntu 24.04, Debian Trixie) and Windows (Server 2022 ltsc2022), each in base and dev flavors. Runners are semi-ephemeral: each container handles exactly one job then exits, while named Docker volumes persist tool caches across restarts.

Why this image?

GitHub provides an official runner image (ghcr.io/actions/actions-runner) designed for ARC (Actions Runner Controller) on Kubernetes. If you run K8s, ARC is the recommended approach.

This image fills a different gap:

Feature Official (ARC) This image
Linux containers โœ… โœ…
Windows containers โŒ โœ…
Kubernetes required Yes No
docker compose up โŒ โœ…
GitHub App auth (JWT) Via ARC config Built into entrypoint
PAT / registration token auth Via ARC config Built into entrypoint
Semi-ephemeral with warm caches Manual restart: always + volumes
Org-level runners Via ARC Via env var (GITHUB_ORG)
Multi-distro (Ubuntu, Debian) Ubuntu only Ubuntu + Debian

Use this image when: you want self-hosted runners on Docker Desktop, Podman, or any Docker host โ€” without Kubernetes.

Use the official image when: you have a Kubernetes cluster and want to use ARC.

Verify this image

Every build ships a Sigstore-signed SBOM and a full Trivy scan โ€” verify them yourself, no login required:

gh attestation verify oci://ghcr.io/oorabona/github-runner:2.332.0 --owner oorabona

Full walkthrough (SBOM payload, Trivy findings, multi-arch manifest inspection, upstream dependency tracking) โ†’ https://oorabona.github.io/docker-containers/verify-images/

Quick Start

# Copy and fill in the env file
cp .env.example .env
# Edit .env: set GITHUB_TOKEN + GITHUB_REPOSITORY (or GITHUB_ORG)

# Start a single runner
docker compose up

# Start 3 parallel runners
docker compose up --scale runner=3

The container registers itself with GitHub, executes one job, then exits with code 0.

Environment Variables

Variable Required Default Description
RUNNER_TOKEN One of Token/PAT/App โ€” Direct registration token from GitHub UI (expires in 1h)
GITHUB_TOKEN One of Token/PAT/App โ€” PAT with repo or admin:org scope
APP_ID One of Token/PAT/App โ€” GitHub App ID
APP_PRIVATE_KEY One of Token/PAT/App โ€” GitHub App private key (PEM string with literal \n)
APP_PRIVATE_KEY_FILE One of Token/PAT/App โ€” Path to GitHub App PEM file (alternative to APP_PRIVATE_KEY)
GITHUB_REPOSITORY One of Repo/Org โ€” Target repository in owner/repo format
GITHUB_ORG One of Repo/Org โ€” Target organisation name
RUNNER_NAME_PREFIX No runner Prefix for the unique runner name
RUNNER_LABELS No self-hosted,linux,<arch> Comma-separated runner labels
RUNNER_GROUP No Default Runner group name
RUNNER_TOOL_CACHE No /opt/hostedtoolcache Tool cache directory; compose.yaml maps this to a named volume at /cache/tool-cache
GITHUB_API_URL No https://api.github.com Override for GitHub Enterprise Server
ALLOW_ROOT No false Set true to run as root (security risk โ€” testing only)
RUNNER_DISABLE_AUTO_UPDATE No 1 Disable runner agent auto-update (recommended for containers)

Auth Modes

PAT (Personal Access Token)

Requires a PAT with repo scope (repository runner) or admin:org scope (org runner).

docker run --rm \
  -e GITHUB_TOKEN=ghp_xxxxxxxxxxxx \
  -e GITHUB_REPOSITORY=owner/repo \
  ghcr.io/oorabona/github-runner:2.332.0

GitHub App

Requires an App installed on the target repository or organisation. Provide either the PEM content (inline) or a file path.

# PEM content inline (escape newlines as \n)
docker run --rm \
  -e APP_ID=123456 \
  -e APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMII...\n-----END RSA PRIVATE KEY-----" \
  -e GITHUB_REPOSITORY=owner/repo \
  ghcr.io/oorabona/github-runner:2.332.0

# PEM from file (mount the key)
docker run --rm \
  -e APP_ID=123456 \
  -e APP_PRIVATE_KEY_FILE=/run/secrets/app-key \
  -v /path/to/app.pem:/run/secrets/app-key:ro \
  -e GITHUB_REPOSITORY=owner/repo \
  ghcr.io/oorabona/github-runner:2.332.0

JWT generation uses openssl (pure bash, no extra dependencies).

Running on Windows

  1. Go to your repo on GitHub: Settings โ†’ Actions โ†’ Runners โ†’ New self-hosted runner
  2. Copy the registration token from the configure step (it starts with A and is valid for 1 hour)

Linux runners (Podman Desktop or Docker Desktop)

Both Podman Desktop and Docker Desktop can run Linux runner images on Windows via WSL2:

podman run --rm \
  -e RUNNER_TOKEN=AXXXXXXXXXXXXXXXXXX \
  -e GITHUB_REPOSITORY=owner/repo \
  ghcr.io/oorabona/github-runner:2.332.0

Windows runners (Docker Desktop only)

Windows container images require Docker Desktop (or Rancher Desktop with moby engine). Podman does not support Windows containers.

  1. Switch Docker Desktop to Windows containers (right-click tray icon โ†’ โ€œSwitch to Windows containersโ€)
  2. Go to your repo โ†’ Settings โ†’ Actions โ†’ Runners โ†’ New self-hosted runner
  3. Copy the registration token
docker run --rm \
  -e RUNNER_TOKEN=AXXXXXXXXXXXXXXXXXX \
  -e GITHUB_REPOSITORY=owner/repo \
  ghcr.io/oorabona/github-runner:2.332.0-windows-ltsc2022

Note: Windows containers require process isolation (default on Windows Server) or Hyper-V isolation (Windows 11 Pro/Enterprise).

Note: The registration token expires after 1 hour. For persistent runners or scaled deployments, use PAT or GitHub App auth instead โ€” those never expire and can refresh a fresh registration token on every container start.

Pre-installed software

What is included per flavor

Linux โ€” base

Package Purpose
git Source control
curl HTTP client
jq JSON processing
unzip Archive extraction
ca-certificates TLS root certificates
tini PID 1 init (zombie reaping + signal forwarding)
gosu Privilege drop from root to runner at startup

The runner user is also added to the docker group so DooD works without sudo.

Linux โ€” dev

Everything in base, plus the following Tauri / native-addon build prerequisites:

Package Purpose
build-essential GCC toolchain, make
pkg-config Library metadata
libssl-dev OpenSSL headers
libgtk-3-dev GTK 3 headers (Tauri)
libwebkit2gtk-4.1-dev WebKit2GTK headers (Tauri)
libayatana-appindicator3-dev System tray support (Tauri)
librsvg2-dev SVG rendering (Tauri)

Language runtimes (Rust, Node, Python, Go, โ€ฆ) are intentionally not pre-installed โ€” see the setup-action table below.

Windows โ€” base

Package Purpose
git Source control (via Chocolatey)
curl HTTP client (via Chocolatey)
jq JSON processing (via Chocolatey)
unzip Archive extraction (via Chocolatey)
pwsh (PowerShell 7) Default shell for RUN steps and entrypoint

Long-path support (LongPathsEnabled) and git config core.longpaths true are applied at build time.

Windows โ€” dev

Everything in Windows base, plus:

Package Purpose
VS Build Tools 2022 (VCTools workload) MSVC compiler, Windows SDK โ€” required for Tauri, native Node addons, Rust on Windows

What needs a setup-* action

Language runtimes are not pre-installed in any flavor. Use the standard setup actions โ€” with persistent volumes they are downloaded only on the first job.

Tool Pre-installed? Action to use Cached after first run?
Node.js No actions/setup-node@v4 Yes (RUNNER_TOOL_CACHE)
Python No actions/setup-python@v5 Yes
Go No actions/setup-go@v5 Yes
Java No actions/setup-java@v4 Yes
.NET No actions/setup-dotnet@v4 Yes
Rust No dtolnay/rust-toolchain@stable Yes (.cargo volume)
Docker CLI No (DooD available) Mount host socket N/A

Persistent caches

Tip: With restart: always and persistent volumes, setup-* actions download tools only on the first job. Subsequent jobs find them in the RUNNER_TOOL_CACHE volume, matching the performance of pre-installed tools without the image bloat. See Cache Volumes for the full volume list.

Flavors

Flavor Tag suffix Included
base -base runner agent, git, curl, jq, unzip, ca-certificates, libicu-dev, libkrb5-dev
dev -dev everything in base + build-essential, pkg-config, libssl-dev, libgtk-3-dev, libwebkit2gtk-4.1-dev (Tauri prerequisites)

The dev flavor targets Tauri-based build pipelines. Language runtimes (Rust, Node, Python) are NOT pre-installed โ€” use setup-* actions; they will be cached in RUNNER_TOOL_CACHE.

Distros

Distro Tag Notes
Ubuntu 24.04 2.332.0 or 2.332.0-ubuntu-2404-base Default, recommended
Debian Trixie 2.332.0-debian-trixie-base Smaller base image
Windows Server 2022 2.332.0-windows-ltsc2022-base Requires Windows host or --profile windows

Scaling

# Start 5 parallel runners for the same repo
docker compose up --scale runner=5

Each container instance gets a unique name (${RUNNER_NAME_PREFIX}-${HOSTNAME}-${EPOCH}) and registers independently. All share the same named volumes for tool caches.

Cache Volumes

Named Docker volumes persist build tool caches across container restarts. They survive docker compose down (use docker compose down --volumes to remove them).

Volume Container path Purpose
github-runner-tool-cache /cache/tool-cache setup-node, setup-go, etc. (RUNNER_TOOL_CACHE)
github-runner-cargo-cache /home/runner/.cargo Rust cargo registry + compiled deps
github-runner-npm-cache /home/runner/.npm npm global cache
github-runner-nuget-cache /home/runner/.nuget NuGet package cache
github-runner-pnpm-store /home/runner/.pnpm-store pnpm content-addressable store

Docker-outside-of-Docker (DooD)

Allows workflows to run docker commands by sharing the host Docker socket. The runner user is pre-added to the docker group at build time.

# In compose.yaml โ€” uncomment the socket volume:
volumes:
  - /var/run/docker.sock:/var/run/docker.sock

Or with docker run:

docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e GITHUB_TOKEN=... \
  -e GITHUB_REPOSITORY=... \
  ghcr.io/oorabona/github-runner:2.332.0

Security warning: Mounting the Docker socket grants the container full control over the host Docker daemon. Only do this on trusted infrastructure. DinD (Docker-in-Docker with --privileged) is not supported.

Windows Runner

The Windows variant (-windows-ltsc2022) runs on Windows Server 2022 with process isolation (no Hyper-V required).

# Start only the Windows runner (requires a Windows host or Hyper-V)
docker compose --profile windows up

Requirements:

  • Windows Server 2022 or Windows 10/11 with Windows containers enabled
  • Docker Desktop configured for Windows containers
  • No Hyper-V needed (process isolation is the default)

The Windows runner uses PowerShell (entrypoint.ps1) and installs packages via Chocolatey.

Building Locally

# From the repository root:
./make build github-runner 2.332.0

# Build all variants (generates Dockerfiles for all distros ร— flavors):
./make build github-runner

# Build a specific distro + flavor:
./github-runner/generate-dockerfile.sh ubuntu-2404 base
docker build --build-arg RUNNER_VERSION=2.332.0 \
  -f github-runner/Dockerfile.ubuntu-2404-base \
  github-runner/

Troubleshooting

Token expired (HTTP 401)

Registration tokens are valid for 1 hour. The entrypoint fetches a fresh token on every start โ€” if the API returns 401, it retries up to 5 times with exponential backoff (2 s, 4 s, 8 s, 16 s, 32 s). If all attempts fail:

[ERROR] Failed to obtain registration token after 5 attempts.

Check that GITHUB_TOKEN has the correct scope (repo for repository runners, admin:org for org runners).

Name conflicts

If a runner with the same name is already registered, config.sh exits with code 3. The entrypoint treats this as a fatal error and exits non-zero. To avoid conflicts, set RUNNER_NAME_PREFIX to a unique value or use docker compose up --scale runner=N which gives each container a different hostname.

No-network errors at startup

The entrypoint exits immediately on DNS / connection failures (curl exits non-zero). There is no retry for network-unavailable errors โ€” only for HTTP-level failures (4xx/5xx). Ensure the container can reach api.github.com (or your GHES URL).

Orphan runners after SIGKILL

If the container is killed with SIGKILL (OOM kill, docker kill, etc.) the SIGTERM cleanup handler does not run and the runner stays registered as offline on GitHub. GitHub automatically removes offline runners after 14 days, but the cleanup-offline-runners.sh script lets you remove them immediately.

# Dry-run: list offline runners without removing (default)
./github-runner/cleanup-offline-runners.sh owner/repo

# Org-level
./github-runner/cleanup-offline-runners.sh --org myorg

# Actually remove them
./github-runner/cleanup-offline-runners.sh owner/repo --force

# Uses GITHUB_REPOSITORY or GITHUB_ORG from the environment
./github-runner/cleanup-offline-runners.sh --force

The script requires the gh CLI to be authenticated (or GITHUB_TOKEN in the environment with repo scope for repository runners or admin:org scope for org runners). It always prints a table of offline runners before acting.

Volume UID mismatch

If a cache volume was created by a different UID, the entrypoint attempts chown on startup and warns if it cannot fix the permissions:

[WARN]  Cache directory not writable: /cache/tool-cache โ€” attempting permission fix

To reset: docker volume rm github-runner-tool-cache (loses cached data).