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.