No KYC · US and Europe, one price in six cities · Pay in BTC, USDT, USDC, ETH, SOL, LTC
Order a VPS

Guide · CI/CD · Runners

How do I run a self-hosted CI runner on a VPS?

GitLab Runner, the GitHub Actions runner and Forgejo Runner on a Linux VPS: current versions, install and registration commands, who should be allowed to send jobs, how many jobs each plan can take, and how to stop images from filling the disk.

Last updated: · 8 min read

Quick answer

How do I run a self-hosted CI runner on a VPS?

Install the runner agent, register it with a token from your Git host, and run jobs in Docker or Podman containers so each build starts clean. On 3 November 2026 the current releases were GitLab Runner 19.5.2, GitHub Actions runner 2.338.2 and Forgejo Runner 13.2.1. On VPS With Crypto, Kilo (2 vCPU / 4 GB / 65 GB) takes one container job at a time. Keep self-hosted runners away from public repositories.

Which runner software, and which version?

Use the agent of the forge that hosts your code; all three run on the Debian and Ubuntu images of every plan. The runner asks its forge for work over HTTPS; GitHub's stated network requirement is outbound HTTPS on port 443.

Versions read on each project's release page on 3 November 2026.
RunnerRelease on 3 Nov 2026How it installsClean environment per job
GitLab Runner19.5.2 (28 October 2026)apt package from packages.gitlab.comWith the Docker executor; the Shell executor gives none
GitHub Actions runner2.338.2 (26 October 2026)Tarball, config.sh, then svc.sh for systemdNo: jobs run on the VPS unless the workflow sets a container
Forgejo Runner13.2.1 (29 October 2026)Single binary, verified with GPGWith Docker, Podman or LXC; host mode has no isolation

How do I install GitLab Runner with the Docker executor?

Install Docker Engine, then GitLab's package, then register with a runner authentication token. GitLab's documentation asks you to download its repository script and read it before running it. The token comes from the project or group settings when you create a runner, and starts with glrt-.

After registration, set concurrent in /etc/gitlab-runner/config.toml to the number of jobs the VPS should run at once, and give each job container a cpus and memory limit under [runners.docker]. Leave privileged off for code you do not fully trust: GitLab's Docker executor page says privileged mode disables container security mechanisms and exposes the host to privilege escalation.

Debian or Ubuntu
# Docker Engine (Debian and Ubuntu package it as docker.io)
sudo apt install docker.io
# GitLab's repository script: read it before running it
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" -o script.deb.sh
less script.deb.sh
sudo bash script.deb.sh
sudo apt install gitlab-runner
# RUNNER_TOKEN holds the glrt- token created in GitLab
sudo gitlab-runner register --non-interactive \
  --url "https://gitlab.com/" \
  --token "$RUNNER_TOKEN" \
  --executor "docker" \
  --docker-image debian:13 \
  --description "vps-runner"

How do I add a GitHub Actions self-hosted runner?

From the repository: Settings, Actions, Runners, New self-hosted runner, then Linux and x64. GitHub shows the download and config.sh commands for the current release; the registration token inside them expires after one hour. Run them as an ordinary user, not root, then install the runner as a systemd service.

The runner updates itself by default. Turn that off and GitHub stops queuing jobs to a runner not updated within 30 days of a new release. Jobs run directly on the VPS under the runner's user unless the workflow declares a container:. The --ephemeral option of config.sh limits a registration to one job.

In the runner's directory, after the download step shown by GitHub
./config.sh --url https://github.com/OWNER/REPO --token TOKEN_FROM_THE_RUNNERS_PAGE
sudo ./svc.sh install
sudo ./svc.sh start
sudo ./svc.sh status

How do I set up a Forgejo Runner?

Download the binary, check its signature, create a runner user, then register and start the daemon. Forgejo's documentation is blunt about what the agent does: it performs remote code execution. Jobs run in Docker, Podman or LXC containers that you install separately. Host mode needs none of them, and Forgejo warns that it gives no isolation at all: one job can wreck the machine.

Forgejo Runner has no default configuration path. Generate a file and pass it with -c every time the daemon starts.

Install Forgejo Runner 13.2.1 (amd64)
export RUNNER_VERSION=13.2.1
export URL="https://code.forgejo.org/forgejo/runner/releases/download/v${RUNNER_VERSION}/forgejo-runner-${RUNNER_VERSION}-linux-amd64"
wget -O forgejo-runner "$URL"
wget -O forgejo-runner.asc "$URL.asc"
gpg --keyserver hkps://keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
gpg --verify forgejo-runner.asc forgejo-runner
sudo install -m 0755 forgejo-runner /usr/local/bin/forgejo-runner
sudo useradd --create-home runner
# then, as the runner user, in /home/runner
forgejo-runner generate-config > /home/runner/runner-config.yml
forgejo-runner register
forgejo-runner daemon -c /home/runner/runner-config.yml

Who should be allowed to run code on the runner?

Only people you would give a shell on the VPS. A CI job is code that runs on your server. GitHub's security guide says self-hosted runners should almost never be used for public repositories, because anyone can open a pull request whose workflow runs on your machine. The same holds for GitLab and Forgejo projects that accept outside contributions.

The same guide warns that a runner not wiped between jobs can be persistently compromised by one bad job.

  • Run jobs in containers, and keep the Docker socket out of untrusted jobs.
  • Give test jobs no deployment secrets; deploy from a second runner on its own VPS.
  • Use short-lived registrations, such as --ephemeral on GitHub, when you can rebuild the runner automatically.
  • Lock down SSH on the runner like any server: keys, not passwords.

Which plan for how many parallel jobs?

Size by RAM per job first. GitHub's hosted Linux runner for private repositories has 2 CPU, 8 GB of RAM and 14 GB of SSD; for public repositories it has 4 CPU, 16 GB and 14 GB (GitHub documentation, read 3 November 2026). A job that fits on that machine needs the same memory on yours. The vCPU of every plan are shared: they are scheduled on physical cores that neighbouring VPS also use. The RAM and NVMe space of your plan are reserved for your VPS only. A build that keeps every vCPU busy for a long time shares cores with neighbors, so expect build times to vary more than on dedicated cores.

Starting points from memory per job, not build timings. Sizes are vCPU / RAM / NVMe.
PlanSizeconcurrentFits
Byte1 vCPU / 2 GB / 40 GB1Linting and unit tests in Python, Node.js or Go; container images soon fill the disk
Kilo2 vCPU / 4 GB / 65 GB1One container job: most web application pipelines
Mega2 vCPU / 6 GB / 120 GB1 to 2One job with a database service container, or two light jobs
Giga4 vCPU / 8 GB / 160 GB2Two jobs of 4 GB, or one with the memory of GitHub's private-repository runner
Tera8 vCPU / 24 GB / 400 GB3 to 6Three jobs of 8 GB or six of 4 GB, with room for image builds

How do I keep the runner's disk from filling up?

Clean containers, volumes and images on a schedule. GitLab Runner installs a clear-docker-cache script and recommends running it from cron, for example once a week; it removes unused containers and volumes but not images. docker system prune removes unused containers, networks, images and build cache, and its until filter keeps the recent ones that make the next job faster.

No plan includes backups, so keep your own copy of anything that matters. A runner is cheap to rebuild: keep its configuration file and your install notes elsewhere, and let the caches go.

Weekly cleanup, from root's crontab
# containers and volumes left by GitLab jobs
/usr/share/gitlab-runner/clear-docker-cache
# images, networks and build cache unused for 3 days
docker system prune -af --filter "until=72h"

Put your runner on a VPS paid in crypto

Root over SSH on Debian or Ubuntu, in six cities across the US and Europe, at one price in each. No KYC: signing up and paying take no identity document, no selfie, no card and no phone number.

Questions about CI runners on a VPS

Can I use GitLab's Shell executor on a VPS?

It works, but GitLab lists it among the executors in maintenance mode, and it gives no clean environment per build: each job sees what the previous one left. Use the Docker executor unless every job is your own trusted code.

Can one VPS run runners for GitHub and GitLab at the same time?

Yes, as separate agents. They share the same vCPU, RAM and disk, so count their jobs together when you set concurrency.

Does pulling Docker images count against my traffic?

Plans state their allowance as outbound traffic: Each VPS comes with a dedicated IPv4 address and a routed IPv6 /64. Every plan lists its outbound traffic per month in TB, and going over it never triggers an automatic charge. Pushing images, artifacts and caches to a registry is outbound traffic.

Should GitLab or Forgejo itself run on the same VPS as its runner?

No. A heavy pipeline then slows the web interface you use to watch it, and a job that escapes its container lands next to your repositories. Give the forge and the runner a VPS each.

Is a self-hosted runner safe for a public open-source repository?

GitHub's guidance is that self-hosted runners should almost never be used for public repositories, because pull requests from forks can run code on your machine. Use the forge's hosted runners for those, and keep yours for private code.

Sources (15)
  1. Self-hosted runners reference (supported systems, outbound HTTPS 443, automatic updates) — GitHub Docs (read 2026-11-03)
  2. Adding self-hosted runners (token valid one hour, private repositories) — GitHub Docs (read 2026-11-03)
  3. Configuring the self-hosted runner application as a service — GitHub Docs (read 2026-11-03)
  4. Secure use reference: self-hosted runners — GitHub Docs (read 2026-11-03)
  5. GitHub-hosted runners reference (standard Linux runner specs) — GitHub Docs (read 2026-11-03)
  6. actions/runner releases (v2.338.2) — GitHub (read 2026-11-03)
  7. Install GitLab Runner using the official repositories — GitLab (read 2026-11-03)
  8. Registering runners — GitLab (read 2026-11-03)
  9. GitLab Runner executors (maintenance mode, clean build environment) — GitLab (read 2026-11-03)
  10. Docker executor (privileged mode, clear-docker-cache) — GitLab (read 2026-11-03)
  11. GitLab Runner releases (v19.5.2) — GitLab (read 2026-11-03)
  12. Forgejo Runner installation from binary — Forgejo (read 2026-11-03)
  13. Forgejo Runner installation overview (remote code execution warning) — Forgejo (read 2026-11-03)
  14. Forgejo Runner releases (v13.2.1) — Forgejo (read 2026-11-03)
  15. docker system prune — Docker Docs (read 2026-11-03)

From $2.25/month on 12 months · no KYC

Order a VPS