Skip to content

Guide · GitHub’s docs read 2026-10-14

Self-hosted GitHub runners: setup, security and cost

A self-hosted runner is a machine you own running GitHub’s runner application, picking up GitHub Actions jobs instead of GitHub’s own fleet. Setting one up takes ten minutes. Running them safely, at the size a team needs, is the part worth reading about first. Everything below about GitHub comes from GitHub’s own documentation, linked where it is used.

Setting one up

Register a runner, then run it as a service

A runner can be added to a repository, an organisation, or (on GitHub Enterprise Cloud) an enterprise. In the repository or organisation settings, under Actions, then Runners, choose New self-hosted runner. GitHub generates the commands for your platform, including a registration token that expires after one hour. On Linux they look like this:

shell
mkdir actions-runner && cd actions-runner curl -O -L https://github.com/actions/runner/releases/download/v<version>/actions-runner-linux-x64-<version>.tar.gz tar xzf ./actions-runner-linux-x64-<version>.tar.gz ./config.sh --url https://github.com/<owner>/<repo> --token <token> sudo ./svc.sh install && sudo ./svc.sh start

Copy the real download line from GitHub’s page or from the runner’s releases; the version changes often. ./run.sh runs it in the foreground instead of as a service. The runner is published for Linux, Windows and macOS on x64, ARM64 on all three (in public preview), and ARM32 on Linux.

Jobs reach it by label. Every self-hosted runner gets self-hosted plus its operating system and architecture, so a workflow asks for one like this:

.github/workflows/ci.yml
jobs: test: runs-on: [self-hosted, linux, x64]

Security

GitHub’s own warning about public repositories

Self-hosted runners should almost never be used for public repositories on GitHub, because any user can open pull requests against the repository and compromise the environment.

That is GitHub’s security guidance, which also warns that a self-hosted runner can be persistently compromised by untrusted code in a workflow. A runner that is reused between jobs carries whatever the last job left behind: files, processes, credentials in a cache. The defence is to never reuse one, which is the next section.

Scaling

Ephemeral runners, just-in-time runners and ARC

Register a runner with --ephemeral and GitHub de-registers it after one job. GitHub recommends autoscaling with ephemeral runners, and recommends against autoscaling persistent ones. Just-in-time runners, created through the REST API, also run at most one job; GitHub’s guidance is to make sure each one starts in a clean environment rather than on reused hardware.

On Kubernetes, the supported route is Actions Runner Controller, an operator that scales runner scale sets up and down with demand. GitHub calls it the recommended Kubernetes-based solution for autoscaling, and supports only its current Autoscaling Runner Sets version.

Upkeep

The rules a fleet has to keep up with

  • Updates. A runner that goes 30 days without a software update stops receiving jobs, and a critical security update can stop them sooner (reference).
  • Offline runners. One that has not connected for more than 14 days is removed automatically; an ephemeral one after more than a day (removing runners).
  • Limits. A job may run for 5 days and a workflow run for 35; a job queued for 24 hours is cancelled (limits).

Cost

Free per minute, and what the hardware bill does not show

GitHub’s billing documentation says Actions usage is free for self-hosted runners; you pay for the machines. On 2025-12-16 GitHub announced a $0.002 per minute platform charge on self-hosted usage from 2026-03-01, and the next day postponed it to re-evaluate. As of 2026-10-14 no new date has been published, and GitHub has said postponed, not cancelled.

The larger cost is the work. Everything above is yours: images and their patching, the 30-day update rule, autoscaling, making every job start clean, a cache close enough to the runners to be worth having, and someone on call when the queue backs up at 3am. For a team with an infrastructure function and a reason to own the hardware, that is a fair trade. For a team that wanted faster CI, it is a second product to run.

That second case is what we sell: managed GitHub runners, where the change is one runs-on label and every job gets its own virtual machine, destroyed when the job ends. Hosted, self-hosted and managed GitHub runners compared sets the three side by side, including where we are the wrong answer, and the pricing page has our rates, read from the rows that bill them.

Questions

What people ask about self-hosted runners

Are self-hosted GitHub runners free?

GitHub charges nothing per minute for them today: its billing documentation says Actions usage is free for self-hosted runners. You pay for the machines and for running them. GitHub announced a $0.002 per minute platform charge on self-hosted usage from 1 March 2026, then postponed it the following day to re-evaluate; it has not published a new date, and it has not said the charge is cancelled.

Can I use a self-hosted runner on a public repository?

GitHub's own guidance is that self-hosted runners should almost never be used for public repositories, because anyone can open a pull request against the repository and compromise the environment. Use them with private repositories, and prefer ephemeral runners even there.

What is an ephemeral runner?

A runner registered with --ephemeral, which GitHub automatically de-registers after it has processed one job. GitHub recommends autoscaling with ephemeral runners and recommends against autoscaling persistent ones. Just-in-time runners, created through the REST API, also run at most one job.

What is Actions Runner Controller?

ARC is a Kubernetes operator that orchestrates and scales self-hosted runners, using runner scale sets. GitHub describes it as its recommended Kubernetes-based solution for autoscaling self-hosted runners, and supports only the current Autoscaling Runner Sets version; the legacy version is community-supported.

Do self-hosted runners need updating?

Yes. If a runner goes 30 days without a software update, GitHub stops queueing jobs to it, and a critical security update can stop jobs sooner. A runner that has not connected for more than 14 days is removed automatically; an ephemeral one after more than a day.

How long can a job run on a self-hosted runner?

Up to 5 days of execution time per job, and 35 days per workflow run, per GitHub's limits page. A job that waits in the queue for 24 hours without being picked up is cancelled.

What is the alternative to running my own?

GitHub's hosted runners, or a managed runner provider such as us: you change the runs-on label and someone else runs the fleet. We are Linux x64 only, so if you need macOS, Windows, ARM64 or GPUs, self-hosting or GitHub's own runners are the right answer and we are not.