setup-self-hosted-gh-runner

Configure ephemeral rootless Podman containers as self-hosted GitHub Actions runners via a systemd user service.

10|1|Updated Jul 7, 2026
One-click install
npx skills add https://github.com/catalystctl/catcode --skill setup-self-hosted-gh-runner-catalystctl
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: setup-self-hosted-gh-runner
Source: https://github.com/catalystctl/catcode/tree/main/.catalyst-code/skills/setup-self-hosted-gh-runner
Command: npx skills add https://github.com/catalystctl/catcode --skill setup-self-hosted-gh-runner-catalystctl

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? GitHub-hosted runners are slow due to cold caches and queue times, and bare-metal or Docker-based self-hosted runners lack isolation or require a root daemon. This Skill sets up a secure self-hosted GitHub Actions runner where each CI job runs in a fresh rootless Podman container that is destroyed after the job. ## Core Features & Use Cases - Ephemeral isolated runners: Each job runs in a fresh container via config.sh --ephemeral and podman run --rm, with rootless user-namespace mapping so jobs have no real host privileges. - Token hygiene and supervision: A supervisor script mints short-lived registration tokens per spawn via the GitHub API while the high-value PAT stays on the host, and a lingered systemd user service keeps runner slots alive. - Use Case: A team with a Linux box running Podman wants faster CI for a Rust/Go repository. Use this Skill to build the runner image, configure per-slot cache volumes, convert workflows from runs-on: ubuntu-latest to self-hosted labels, and verify jobs land on the new runners. ## Quick Start Set up a secure self-hosted GitHub Actions runner on my Linux machine using ephemeral rootless Podman containers managed by a systemd user service.

Frequently Asked Questions about setup-self-hosted-gh-runner

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I set up a self-hosted GitHub Actions runner with Podman?▼

Build a runner image from an ubuntu:24.04 base with the actions-runner tarball and required toolchains, then run it with podman run --rm and config.sh --ephemeral. A supervisor script mints a fresh registration token per spawn via gh api -X POST, and a systemd user service keeps the slots alive.

How do I run GitHub Actions runners in rootless containers securely?▼

Use rootless Podman so container root maps to an unprivileged host user via user namespaces, combined with ephemeral containers destroyed after each job. The high-value GitHub PAT stays on the host and only short-lived registration tokens enter containers.

Why does the GitHub runner fail with 'Must not run with sudo' in Podman?▼

Rootless Podman maps the host user to container uid 0, and the runner refuses to run as root. Fix it by setting the environment variable RUNNER_ALLOW_RUNASROOT=1, passed via podman run -e or baked at the end of the Containerfile.

Why does the runner listener crash with an ICU package error?▼

The runner listener is a .NET 6 app that needs libicu and related libraries. Run ./bin/installdependencies.sh from the /runner directory during image build to install libicu, liblttng-ust, and krb5.

When should jobs stay on GitHub-hosted runners instead of rootless Podman?▼

Keep jobs on ubuntu-latest when they need kernel features unavailable in a rootless user namespace, such as FUSE mounts, AppImage, or certain device access. Also skip this setup if the box lacks Podman entirely.

Can concurrent runner containers share one cache volume?▼

No, concurrent containers on the same volume race on cargo-registry and go-mod writes. Give each slot its own named volume, and mount only pure caches like GOMODCACHE and GOCACHE while keeping toolchain homes in the image.