GitHub Actions Runners — Full Reference
Runner Types
GitHub-Hosted Standard - Labels: ubuntu-latest, windows-latest, macos-latest - Hosted on Azure (Linux/Windows) or GitHub’s own macOS cloud. - Free and unlimited for public repos. Private repos consume plan minutes (Linux 1x, Windows 2x, macOS 10x multiplier). - Free plan: 2,000 min/mo. Pro: 3,000. Team: 3,000. Enterprise Cloud: 50,000.
GitHub-Hosted Larger Runners (Team/Enterprise only) - Up to 96 vCPU / 384 GB RAM / 2040 GiB SSD (GA April 2025), with static IPs, autoscaling, and runner groups. - Billed per-minute only when running a job. No idle cost. Included plan minutes don’t apply.
Self-Hosted - Your own hardware, your rules. Full control over environment, software, networking. - Connects to GitHub via a lightweight HTTPS agent — no inbound ports needed. GitHub dispatches jobs; runner picks them up, executes, sends logs back.
Self-Hosted: Pricing Update (Important)
From March 1, 2026, GitHub charges $0.002/min for self-hosted runner usage on private repos. Public repos and GitHub Enterprise Server are unaffected. Still cheaper than hosted runners at scale, but worth factoring in.
Ephemeral vs Persistent Runners
GitHub recommends ephemeral runners for autoscaling. With ephemeral runners, GitHub only assigns one job per runner, guaranteeing a clean environment. Add --ephemeral to config.sh and the runner auto-deregisters after one job.
Autoscaling with persistent runners is not recommended — GitHub can’t guarantee jobs won’t be assigned while a runner is shutting down.
Running a Runner on Proxmox
You have two sensible options: LXC container (lighter, faster) or VM (full isolation, better for Docker-in-Docker).
Option 1: LXC Container (Recommended for Most Cases)
Creating an LXC container in Proxmox VE offers efficient resource management and isolation. A Debian-based LXC with 2 CPU cores and 1 GB RAM is sufficient for moderate CI/CD workloads like building static sites or running basic tests.
Quickest path — use the community script:
# Run on your Proxmox host
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/docker.sh)"This spins up an LXC with Docker pre-installed.
⚠️ Security note: Since the container has Docker support, it cannot run unprivileged. This approach is more insecure than a full VM, at the benefit of being much faster. Only use this runner in contexts you control at all times (e.g. private repos).
Option 2: VM (Full Isolation, Docker-in-Docker safe)
Create a standard Ubuntu 22.04/24.04 VM in Proxmox. Recommended if you’re running Docker builds or need full kernel isolation. You can use a Cloud-Init template for fast provisioning.
Step-by-Step: Install the Runner (inside LXC or VM)
1. Create a dedicated user
useradd -m -G sudo -s /bin/bash runner
passwd runner
# If doing Docker builds:
usermod -aG docker runner2. Download and extract the runner
Go to your repo → Settings → Actions → Runners → New self-hosted runner. GitHub generates the exact download URL and registration token for you. It looks like:
mkdir actions-runner && cd actions-runner
curl -o runner.tar.gz -L https://github.com/actions/runner/releases/download/v2.334.0/actions-runner-linux-x64-2.334.0.tar.gz
tar xzf runner.tar.gz3. Configure
./config.sh \
--url https://github.com/YOUR_ORG_OR_USER/YOUR_REPO \
--token YOUR_REGISTRATION_TOKEN \
--name proxmox-runner-01 \
--labels self-hosted,linux,proxmox,docker \
--work _work
# optionally add --ephemeral for single-useLabels are how your workflows find the right runner. If you have multiple runners with different capabilities (e.g. one with Docker, one without), use labels to route jobs to the correct machine.
4. Install as a systemd service
For Linux systems that use systemd, the svc.sh script is created after successfully adding the runner and can be used to install and manage the application as a service.
sudo ./svc.sh install
sudo ./svc.sh start
sudo ./svc.sh statusThe runner now survives reboots automatically.
5. Verify
# Live logs
journalctl -u actions.runner.YOUR-ORG-REPO.proxmox-runner-01.service -fYou should see Listening for Jobs.
Using the Runner in a Workflow
jobs:
build:
runs-on: [self-hosted, linux, proxmox]
steps:
- uses: actions/checkout@v4
- name: Build
run: docker build .The runs-on array must match all labels on a single runner.
Organisation-Level Runner (Recommended)
If you’re running multiple repos under one org, register at the org level instead of per-repo — Settings → Actions → Runners at the org level. All repos in the org can then use it, and you manage runners in one place.
Security Hardening
- Only use self-hosted runners on private repos (public repos allow any fork PR to run arbitrary code on your machine)
- Run as a non-root dedicated system user with no login shell
- Use
--ephemeral+ a reset mechanism so each job gets a clean environment - Put the runner LXC/VM on its own VLAN if it needs to access internal services
- If you disable automatic runner updates, you must still update within 30 days of a new version release or jobs may fail.
Monitoring & Logs
The runner creates a detailed log file for each job in the _diag directory. The systemd service naming convention is actions.runner.<org>-<repo>.<runnerName>.service.
# Live service logs
journalctl -u actions.runner.* -f
# Per-job logs
ls ~/actions-runner/_diag/Worker_*.logProxmox-Specific Tips
- Snapshots: Before registering a runner, snapshot the LXC/VM. If a build corrupts the environment, roll back and re-register.
- Cloud-Init template: Build a VM template with the runner pre-installed but not yet registered. Clone it and pass the registration token via Cloud-Init user data for fast ephemeral VMs.
- Resource sizing: 2 vCPU / 2 GB RAM is fine for basic builds. Django + Node builds with Docker: 4 vCPU / 4–8 GB RAM is more comfortable.
- Persistent caches: Unlike GitHub-hosted runners, your Proxmox runner retains the
_workdirectory between jobs — pip, npm, and Docker layer caches persist automatically, making builds significantly faster.