On this page
  1. What is a CI runner?
  2. Hosted vs self-hosted: what actually differs?
  3. When do you actually need a self-hosted runner?
  4. How do self-hosted runners leak credentials?
  5. Where AI coding assistants get this wrong
  6. Checklist
  7. FAQ
    1. Is a CI runner the same as a build server?
    2. Can I use my own laptop as a runner?
    3. Why are hosted runners slower on the first run?
    4. Do self-hosted runners save money?
  8. Related topics
  9. Sources
concept

What Is a CI Runner (and When Do You Need Your Own)?

The runner executes pipeline jobs. Hosted runners are ephemeral and easy; self-hosted ones are cheaper at scale and a credential risk if done wrong.

Quick answer

  • A runner is the process or machine that picks up a pipeline job and executes its steps; hosted runners are provided per job, self-hosted ones you operate.
  • Hosted runners are ephemeral, patched, and start clean, which makes them the safer default for public repositories.
  • Self-hosted runners make sense for private network access, large caches, GPUs, or a build volume where per-minute pricing dominates.
  • A persistent self-hosted runner keeps workspace, caches, and credentials on disk between jobs, so one malicious job can poison later builds.
  • Never attach a self-hosted runner to a public repository unless untrusted jobs are isolated in ephemeral, unprivileged environments.

What is a CI runner?

A runner is the execution environment for a pipeline job. The CI service decides what should run and when; the runner checks out the code, runs the steps, streams logs back, and reports the result. In GitHub Actions the runner is an agent process; in GitLab it is a runner registered with a token; in Jenkins it is a node.

Runners come in two shapes. Hosted runners are created for a job from a clean image and destroyed afterwards. Self-hosted runners are machines you register and keep, which can be a laptop, a VPS, or a Kubernetes pod. The difference in lifecycle is the difference in almost every security and performance property.

Hosted vs self-hosted: what actually differs?

The comparison that matters is not price per minute but the state each option carries. A hosted runner starts from a known image with nothing from previous jobs. A persistent self-hosted runner keeps the workspace, package caches, Docker layers, and any credentials left in the environment, which makes builds faster and incidents easier to cause.

| Attribute            | Hosted runner                     | Self-hosted runner                      |
|----------------------|-----------------------------------|------------------------------------------|
| Lifecycle            | Fresh per job                     | Long-lived, reused                       |
| Patching             | Provider                          | You                                      |
| Network access       | Public, no private VPC by default | Can reach private networks               |
| Cache warmth         | Cold unless configured            | Warm, sometimes too warm                 |
| Cost model           | Per minute                        | Fixed compute plus your time             |
| Untrusted PR risk    | Contained by ephemerality         | High — workspace and secrets persist     |
| Best for             | Most projects, public repos       | Private network, GPU, heavy builds       |

When do you actually need a self-hosted runner?

Four legitimate reasons: the build must reach a private network or database that cannot be exposed; the workload needs hardware hosted runners do not offer, such as a GPU or a large memory machine; the build is dominated by cache warm-up that ephemeral machines cannot amortize; or the monthly hosted bill exceeds the cost of the machine and the maintenance.

Convenience is not on the list. A self-hosted runner on a VPS that also serves production couples your deploy capacity to your app server, and a fork bomb in a test now affects users. Keep build and production separate even when both run on one provider.

How do self-hosted runners leak credentials?

Through persistence. A job writes a token to a file in the workspace, the workspace survives, and the next job — possibly from a different branch or a fork — can read it. Environment variables set for one job can remain in the agent’s process environment. Docker images and layers stay in the local daemon, including layers built with secrets.

The controls are structural: run each job in a fresh container or VM, mount a clean workspace, never expose the runner to fork pull requests, and give the runner an identity that can read artifacts but not production secrets. If a runner must hold a deploy credential, scope it to one environment and rotate it on a schedule.

Where this bites vibecoders

A generated CI setup will use the host’s default runner, which is correct. The problem appears later, when a build needs a private database and someone installs a runner on the production VPS to reach it. That single decision puts build jobs and user traffic on one machine and gives every test job the production machine’s network identity.

Where AI coding assistants get this wrong

  • Registering a self-hosted runner on a public repository that accepts fork pull requests.
  • Running the runner as root on a host that also serves production.
  • Leaving the workspace and Docker cache shared between unrelated jobs.
  • Giving the runner a long-lived cloud key instead of a scoped, short-lived identity.
  • Assuming hosted runners can reach a private VPC without configuration.
  • Installing build tools and credentials directly on the host instead of in the job image.

Checklist

  • Use hosted runners unless you can name the constraint that prevents it.
  • Run self-hosted jobs in an ephemeral container or VM.
  • Never attach a self-hosted runner to untrusted pull requests.
  • Give the runner a scoped identity, not a personal or production credential.
  • Keep the runner host separate from production workloads.
  • Patch the runner image and rotate its credentials on a schedule.

FAQ

Is a CI runner the same as a build server?

Close. A build server usually refers to the whole system that schedules and runs builds; a runner is the worker that executes one job. Modern services split the two so scheduling is managed and execution can scale horizontally across many runners.

Can I use my own laptop as a runner?

You can, and it works for personal projects where the machine is only used by you. It is a poor choice for anything shared, because the machine sleeps, moves networks, and holds your personal credentials. A small VPS with an ephemeral job container is more predictable.

Why are hosted runners slower on the first run?

Because nothing is cached. Dependencies, compiler output, and container layers must be downloaded or rebuilt. That is the price of a clean environment. Add a keyed dependency cache and a remote build cache rather than making the runner persistent.

Do self-hosted runners save money?

Sometimes, but the saving is easy to overstate. You trade per-minute billing for a machine, patching, monitoring, and the security work of isolating jobs. It pays off when builds are long, caches matter, or the workload needs special hardware; it rarely pays off for a small project with short builds.

Sources

Share: