Some links on this page are affiliate links: if you sign up through them, this site earns a commission at no extra cost to you. Prices and recommendations are not affected.

Every “run your CI for free” guide stops at the same point: GitHub gives you free minutes, and self-hosted runners are free. Neither statement is wrong, and neither tells you what a runner actually costs. This one does the arithmetic with the numbers GitHub publishes today, and a VPS price we benchmarked ourselves.

What GitHub-hosted runners cost per minute

The headline number is $0.006 per minute for a standard 2-core Linux runner, and it only applies once your included minutes are gone. Before that you are not paying per minute at all; you are spending down a monthly allowance.

RunnerPer-minute rate (USD)
Linux 1-core (x64)$0.002
Linux 2-core (x64)$0.006
Linux 2-core (arm64)$0.005
Windows 2-core$0.010
macOS 3-4 core$0.062

Two things hide inside that table. First, GitHub rounds every job up to the nearest whole minute, so a 30-second job bills as one minute. Second, arm64 is cheaper than x64 ($0.005 vs $0.006) - worth switching your public runner to an Arm label when your stack builds on Arm.

Larger runners are a different ladder: Linux 4-core is $0.012/min, 8-core $0.022, 16-core $0.042, up to 96-core at $0.252. Those only matter when you parallelise inside a single job, and they are not available on the Free plan at all.

The free tier, in minutes

“Free” means an included amount of compute, not unlimited minutes. The monthly allowance, converted to standard Linux minutes at $0.006:

PlanIncluded computeStandard Linux minutes
Free$122,000
Pro$183,000
Team$183,000
Enterprise Cloud$30050,000

Two rules matter more than the table. Public repositories get unlimited standard hosted runners for free - the minutes above only apply to private repos. And self-hosted runners are free, always, and do not draw from your included compute at all. That second rule is the entire business case for running your own.

The break-even: when a VPS beats GitHub

A self-hosted runner costs whatever the machine costs, and the minutes are free. The question is how many hosted minutes that machine must replace before it pays for itself.

Take the Hetzner CX23 we benchmarked for our VPS comparison: 2 vCPU / 4 GB / 40 GB at €5.49 a month, roughly $6. At $0.006 per Linux minute, $6 buys exactly 1,000 hosted minutes. So the CX23 breaks even the month you would otherwise run 1,000 paid minutes - that is, minutes beyond your free allowance.

Worked example on the Free plan:

  • You get 2,000 Linux minutes free.
  • You actually need 4,000 minutes (a busy private repo, or several).
  • Hosted cost: (4,000 - 2,000) × $0.006 = $12.
  • Self-hosted cost: €5.49 ≈ $6, unlimited minutes.
  • You are ahead from month one, and every extra minute is free.

The same math on Pro (3,000 included): self-hosted wins once you pass 3,000 + 1,000 = 4,000 minutes a month. Below that, hosted is cheaper, because you already pay for Pro and the allowance covers you.

The part the arithmetic hides

The VPS is on whether or not a build is running. Hosted runners bill only for minutes used. That asymmetry decides the whole thing:

  • Steady, heavy CI - nightly builds, a monorepo with many jobs - self-hosted wins in the first heavy month and keeps winning.
  • Bursty CI - a few pushes a week, minutes here and there - you stay inside the free tier and hosted costs nothing. A €5.49 VPS is €5.49 you did not need to spend.
  • Short jobs - GitHub’s round-up-to-the-minute punishes 20-second jobs. A self-hosted runner has no per-minute meter to round, so a hundred 20-second jobs are just… time.

There are two more self-hosted advantages that are not about money. Hosted jobs cap at 6 hours; a self-hosted runner has no such ceiling. And hosted concurrency is capped by plan, while a self-hosted runner gives you as many parallel jobs as the machine’s cores allow.

What a self-hosted runner actually costs you

The dollar price is not the whole price. You are now running a service that executes arbitrary code from your repository, and you own the patching, the updates and the security boundary.

Three rules we follow on our own box:

  1. Never on the production host. A runner executes untrusted workflow code. Give it its own VPS, or at minimum its own container with no access to your site, configs or backups.
  2. Ephemeral, not long-lived. Register a fresh runner per job or per day so a poisoned image does not linger. Actions Runner Controller (ARC) does this on Kubernetes; a plain docker run --rm of the runner image does it on a single box.
  3. No secrets in the runner environment. The runner sees only the repo-scoped GITHUB_TOKEN for the jobs it runs. Keep your deploy keys where a job cannot read them - the same reasoning we wrote up in the rsync deploy guide.

The runner itself is one binary or one container you run under Docker; it is not exotic. What is easy to get wrong is everything around it, which is the part with a real cost in your time.

Setting it up is the same on any box: create a runner in Settings → Actions → Runners → New self-hosted runner, copy the download command - it contains your token and the current version - then run config.sh and install it as a service. The GitHub page gives you the exact three commands; the version number changes, the flow does not.

Which to pick

Pick GitHub-hosted if you stay inside the free allowance - private repos under 2,000 minutes a month, or any public repo - you want zero maintenance, and your jobs finish in minutes rather than hours.

Pick a self-hosted runner on Hetzner if you burn through the free tier every month, you need long or highly parallel jobs, or you want builds on the private network next to your servers.

Pick Vultr or DigitalOcean if you need a runner in a region Hetzner does not cover, or per-second billing for a runner you spin up only on demand.

FAQ

Are GitHub Actions free? Public repositories get unlimited standard hosted runners for free. Private repositories get a monthly included amount - $12 of compute on the Free plan, which is 2,000 standard Linux minutes - then pay $0.006 per additional Linux minute.

What does a self-hosted runner cost? The runner software is free. You pay only for the machine it runs on - from about €5.49 a month for a Hetzner CX23 - and for your time maintaining it. Minutes are unlimited.

When is a self-hosted runner cheaper? When your private-repo usage exceeds the free allowance by more than roughly 1,000 Linux minutes a month. Below that, the $6-or-so VPS costs more than the hosted minutes it replaces.

Do hosted runners have limits? Yes. Jobs time out at 6 hours, and concurrency is capped by your plan. Self-hosted runners have no per-minute cost and no 6-hour ceiling, but you own the machine and its updates.

Is a self-hosted runner safe to run? Only if you isolate it. It executes arbitrary code from your repository, so it should never share a host with production workloads, and it should be ephemeral and free of long-lived secrets. Our inherited server audit is the isolation checklist.

What’s next

The machine underneath is the decision you are actually making. The VPS comparison breaks down Hetzner vs DigitalOcean vs Vultr with benchmarks we ran ourselves, and the Caddy + Docker guide shows the single-box setup that keeps a self-hosted runner and a small site on one server without letting them touch.