Runners
A runner is a standalone program that you operate. It asks Forge for queued jobs of one project and runs each in a Docker container on your machine. This page covers what you can configure and what protects the host. To run your first job, start with Your first pipeline.
Scope: one project per runner
Section titled “Scope: one project per runner”Runners are registered per project by project administrators. Instance-wide or group runners shared across Orbit projects are not included, nor is autoscaling, nor any executor other than Docker. Shared runners are Planned. CI minutes and concurrent jobs apply to shared runners only; minutes per plan are on the pricing page. Your own runners do not use minutes.
Lifecycle
Section titled “Lifecycle”| Action | What happens |
|---|---|
| Register | The runner token is shown once; Forge stores a hash. |
| Pause | A paused runner takes no new jobs. |
| Revoke | The runner token stops working. |
| Reset token | An administrator replaces the token. The old token stops working immediately; running jobs keep their own lease tokens. |
The runner list shows each runner as online or offline, with the version, capabilities, scope and limits it reported with its last claim.
Which jobs a runner takes
Section titled “Which jobs a runner takes”- Tags: a job runs on a runner whose tags match the job’s
tags. - Tagged only: a runner can be limited to jobs that have tags (untagged jobs are skipped).
- Protected refs only: the runner takes only jobs of pipelines on protected branches (explicit rules or the default branch) and protected tags. Whether a job’s ref was protected is fixed when the pipeline is created.
- Maximum job timeout: a runner may cap job timeouts from 10 minutes to 24 hours. A job’s effective timeout is the lower of its own and the runner’s.
- Concurrent jobs: the project’s concurrent limit caps claims; one runner process can run several jobs at once.
If no job is picked up, the job’s waiting reason tells you why (for example no runner of the project with its tags, or every matching runner paused or busy).
Isolation
Section titled “Isolation”Every job runs in an ephemeral container:
- non-root, with dropped capabilities, no new privileges and a read-only root filesystem;
- no Docker socket and no Forge service credentials inside the job;
- no network by default, unless the runner is configured with a job network;
- bounded source extraction, bounded logs, and CPU, memory and process limits (defaults: 1 CPU, 512 MB, 128 processes);
- a job timeout or cancellation removes the container before completion is reported;
- symlink and device entries in source and artifact archives are rejected.
Reviewed scripts, images and runner operators remain trusted. Docker on the same machine as the runner, and durable local storage for its state, are required.
Runner settings
Section titled “Runner settings”These environment variables configure the Docker executor of a runner.
| Variable | Meaning |
|---|---|
FORGE_RUNNER_CONCURRENT |
Jobs run at once in one runner process, 1 to 16. Each job gets its own container and workspace. |
FORGE_RUNNER_JOB_CPUS |
CPU limit per job. |
FORGE_RUNNER_JOB_MEMORY_MB |
Memory limit per job in MB; swap equals memory. |
FORGE_RUNNER_JOB_PIDS |
Process limit per job. |
FORGE_RUNNER_PULL_POLICY |
Image pull policy: if-not-present (default), always or never, alone or as an ordered list. |
FORGE_RUNNER_ALLOWED_PULL_POLICIES |
The pull policies that jobs may request with image: {name, pull_policy}. A policy outside the allowlist fails the job. |
FORGE_RUNNER_DOCKER_ENDPOINT |
tcp://host:port of a remote Docker daemon. Requires the three TLS variables below. |
FORGE_RUNNER_DOCKER_TLS_CA_FILE, FORGE_RUNNER_DOCKER_TLS_CERT_FILE, FORGE_RUNNER_DOCKER_TLS_KEY_FILE |
Mutual TLS files. The key file must not be readable by group or others. Plaintext TCP is refused. |
Images are pulled before any workspace or container exists, and the container is created from the resolved image ID. The job log shows the image ID that was used. Private-registry credentials from CI variables are not supported; the Docker daemon’s own registry configuration applies.
A runner stops claiming new jobs when it receives SIGQUIT, lets the running jobs finish and report, then exits with status 0. SIGTERM and SIGINT cancel running jobs.
Recovery after a crash
Section titled “Recovery after a crash”A runner keeps a journal of the containers it creates. If it was killed while a docker create was in flight, it refuses to start and names the command to run. While the runner is stopped:
forge-runner recovery statusforge-runner recovery settle <local-id> --confirm [--quiet-seconds N]status lists the executions the journal tracks, the creation state of each and what Docker holds under its exact names. settle adopts and removes a resource that carries the execution’s signed labels. Otherwise it records a settlement after two absence observations on the same daemon, separated by the quiet window, and then retires the execution so that the runner can start again. A container with forged labels, or a changed Docker daemon, is refused.
Not included
Section titled “Not included”Instance and group runners, autoscaling, executors other than Docker, services: containers, image:entrypoint and fleet-wide runner management across projects.