Workload · Running your CI builds

Your own GitHub Actions self-hosted runner, paid for by the second

A self-hosted runner for GitHub Actions is a small program you install on your own machine so your workflows run there instead of on GitHub's computers. It only needs a 64-bit Linux, Windows or macOS machine that can reach GitHub over HTTPS on port 443, and GitHub's documentation says running jobs on it is free; the machine is the only bill.

The short version
  1. Jobs on your own runner are free on GitHub
  2. Needs only outbound HTTPS, no open ports
  3. Pay for the VPS only while it runs
  4. One clean job per runner with --ephemeral
  5. Keep it to private repositories

Why run your own runner?

Usually for one of three reasons: builds that take a long time, caches you want to keep between jobs, or access to things only your own servers can reach. The runners GitHub provides are easier for small projects, but each job begins on a fresh machine.

What about cost? GitHub says jobs on your own runners cost nothing in Actions; the machine is your expense. Late in 2025 GitHub planned a small per-minute fee for these runners, then paused the plan to think again, so look at GitHub's billing page for the latest before you budget.

What does the machine need?

  • A supported system: recent Ubuntu, Debian, Red Hat, Fedora and similar Linux, on 64-bit Intel or AMD (ARM is in preview).
  • Network: outbound HTTPS on port 443 and at least 70 kbit/s each way. The runner calls GitHub, so nothing has to reach in.
  • Enough power for your build: the runner itself is tiny; your compiler, tests and containers decide how many vCPUs and how much memory you want.
  • Patience in the queue: a job that waits more than 24 hours for a free runner fails.

Pay only while it works

Most runners sit idle between pushes, which is why our Elastic Cloud VPS suits them: you are charged for processing time by the second, only while the server is switched on, while storage and the IPv4 address are charged hourly for as long as you keep the server. Outbound traffic is paid per GB and inbound is free. Nothing is due up front; you save a card, usage is invoiced at the end of the month, and you can release the machine from your dashboard whenever you like.

If your runner will be busy around the clock, the fixed monthly Cloud VPS plans on the same page are the better deal. Both are virtual machines in New York, on shared hosts with unpinned vCPUs, running Ubuntu, Debian, AlmaLinux or Rocky Linux. Need a whole machine for heavy builds? See our dedicated servers.

Up and running in an evening

  1. Order an Elastic VPS with Ubuntu, log in over SSH as root, and create a normal user to install and run the runner under, rather than running it as root.
  2. On GitHub, open your repository's Settings, then Actions, then Runners, and click New self-hosted runner. Choose Linux and copy the download commands it shows.
  3. Run the config.sh command it gives you. The registration token in it is only valid for an hour, so do this straight away.
  4. Add --ephemeral if you want each runner to take a single job and then remove itself.
  5. Start it with ./run.sh, or install it as a service with sudo ./svc.sh install and sudo ./svc.sh start so it survives reboots.

In your workflow file, send jobs to it with runs-on: self-hosted, plus any labels you gave it.

Keeping it safe

GitHub is clear on the big one: keep self-hosted runners away from public repositories, almost without exception, since a stranger's pull request could end up executing on your server. Beyond that:

  • Prefer ephemeral runners. A runner that keeps going between jobs can be left compromised by one bad workflow.
  • Store as few secrets there as you can, because a later job on that runner may be able to read what an earlier one passed on its command line.
  • Block all incoming connections except SSH. The runner only ever talks out to GitHub.
  • Keep the operating system patched. GitHub updates the runner program, not the rest of the machine.

When GitHub's own runners are the better choice

For an open-source project, Windows or macOS builds, or a few quick checks a month, stick with the runners GitHub provides. Our Cloud VPS offers Linux only. If you would rather host the whole code platform yourself, our GitLab guide walks through that instead.

Questions people ask

Do I pay GitHub to use my own runner?
Not today: GitHub lists jobs on your own runners as free, and you cover the server. It had planned a per-minute charge from 2026 and put it on hold, so have a look at GitHub's billing pages for any change.
Do I need to open any ports?
No incoming ones. The runner makes outbound HTTPS connections to GitHub on port 443, so you can block everything coming in except your own SSH.
Can I use it for my public open-source project?
GitHub advises against it. On a public project, any outsider sending a pull request could have their code executed on your server.
What does --ephemeral do?
It tells the runner to take one job and then deregister. For each build to start clean, you still have to reset or rebuild the machine between jobs, for example by reinstalling it from the dashboard. GitHub recommends ephemeral runners when you scale runners up and down.
Does an elastic VPS cost anything when stopped?
Yes, a little. Processing time stops being billed, but the disk and IPv4 address are billed every hour the machine exists. Release it from the dashboard to stop those too.
My registration token stopped working. Why?
Tokens expire one hour after GitHub creates them. Open Settings, Actions, Runners again to get a fresh one.

Get a VPS for your runner

An Elastic Cloud VPS billed by the second while it runs, with nothing to pay up front.

Get my runner VPS

Read next