# Self-hosted runners
Source: https://docs.infraista.com/en/developer-tools/pipelines/self-hosted-runners



A **self-hosted runner** is your own machine (an office server, a GPU workstation, a server on your
private network) that runs pipeline jobs. It asks Infraista for jobs over outbound HTTPS, so no inbound
ports are needed, runs each job in a fresh container, and is **never billed**.

## Before you start [#before-you-start]

* A Linux machine: Ubuntu 20.04+, Debian 11+ or RHEL 8+, x64 or arm64. Docker and the tools the runner
  needs are installed if missing. Or any host with Docker 24+.
* Root access on the machine.
* Permission to manage Pipelines in Infraista.

An organization can have up to 50 self-hosted runners.

## Add a runner [#add-a-runner]

1. Open **Pipelines** > **Runners** and select **Add self-hosted runner**.
2. Enter a **Name** (a number is added if it's taken), **Labels** such as `gpu`, `linux` or `office`
   (`self-hosted` is always added), and the **Group**.
3. Select **Create registration token**. The token works for one hour and for up to 20 machines, and
   is shown only here.
4. Copy the command for how the runner should run, and run it on the machine.

<Shot name="developer-tools/pipelines/add-runner" alt="Add a self-hosted runner, with name, labels, group, the registration token and the install commands" />

### On Linux [#on-linux]

```bash
curl -fsSL https://api.infraista.com/install/runner-agent | sudo bash -s -- prr_… --name build-box --labels gpu,linux
```

This installs the runner as a systemd service. Options at the end of the command:

| Option         | What it does                                                                                                                                                                                                                                                     |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name NAME`  | The runner's name                                                                                                                                                                                                                                                |
| `--labels a,b` | Its labels (besides `self-hosted`)                                                                                                                                                                                                                               |
| `--slots N`    | How many jobs it runs at the same time (default 1)                                                                                                                                                                                                               |
| `--isolation`  | Stronger isolation for jobs, and Docker builds inside jobs. Debian or Ubuntu only. It changes the machine's Docker setup and restarts Docker, so the machine must have no containers at all (stopped ones included); the installer lists any that are in the way |

Re-run the command later to update the runner.

### With Docker [#with-docker]

On any host with Docker 24+, the runner runs in a container and starts job containers through the
Docker socket. The console gives you the full command; it looks like this:

```bash
docker run -d --name build-box --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/infraista-runner:/var/lib/infraista-runner \
  -e INFRAISTA_API=https://api.infraista.com \
  -e REGISTRATION_TOKEN=prr_… \
  -e RUNNER_NAME=build-box \
  -e RUNNER_LABELS=gpu,linux \
  alpine:3.20 sh -c '…'
```

When the runner connects, it appears in the **Self-hosted runners** table as **Online**.

<Shot name="developer-tools/pipelines/runners" alt="The Self-hosted runners table with an online runner, its labels, group and version" />

## Send jobs to it [#send-jobs-to-it]

```yaml
jobs:
  - name: train
    runner: [self-hosted, gpu]
    steps: [...]
```

A job runs on any online runner that has **all** of its labels. `runner: self-hosted` takes any of
your runners. Pull requests from forks never run on self-hosted runners.

## Runner groups [#runner-groups]

Groups decide which pipelines may send jobs to their runners. New runners join the **Default** group,
which allows all pipelines unless you change it.

<Shot name="developer-tools/pipelines/runner-groups" alt="Runner groups, with the Default group allowed for all pipelines" />

To limit a runner to some pipelines, select **New group**, choose the pipelines that may use it, and
pick that group when you add the runner (or when you edit it).

## Manage a runner [#manage-a-runner]

* **Edit**: change its name, labels, group, **Jobs at a time** (1 to 16), or turn off **Takes new jobs** to stop it taking
  jobs without removing it.
* **Remove**: its token stops working right away, and a job it's running is cancelled. Uninstall the
  service on the machine afterwards.

## Related [#related]

* [Runners and billing](/en/developer-tools/pipelines/runners-and-billing)
* [Pipeline file reference](/en/developer-tools/pipelines/pipeline-file-reference)
