Named Runners

Named runners let you deploy isolated runner containers, each with its own config.toml. Jobs are dispatched to a named runner when any of their CI tags match the runner name.

Quick start#

Define a named runner in your config and tag jobs to use it:

# .glciconfig.toml

[runners.gpu]
config_template = """
[[runners]]
  [runners.docker]
    privileged = true
    gpus = "all"
    memory = "16g"
"""
# .gitlab-ci.yml

train-model:
  tags: [gpu]
  image: nvidia/cuda:12.0-devel
  script:
    - python train.py

When you run glci run, the train-model job is routed to the gpu runner container. All other jobs run on the default shared runner.

How it works#

The daemon’s RunnerManager coordinates three tiers of runner containers:

TierContainer nameWhen created
Sharedglci-runner-{suffix}Always (default for all projects)
Per-projectglci-runner-{suffix}-{project}When a project sets [runner] config_template
Namedglci-runner-{suffix}-{project}-{name}When [runners.<name>] is defined

Job dispatch#

  1. For each job, glci checks if any of its tags match a named runner name
  2. First tag match wins — the job is assigned to that named runner
  3. Unmatched jobs go to the default runner (shared or per-project)
  4. Named runners have run_untagged=false — they only receive explicitly tagged jobs

Config templates#

Each named runner accepts a config_template (inline Go template) or config_template_file (path to a template file) that generates its config.toml.

Inline template#

[runners.gpu]
config_template = """
[[runners]]
  [runners.docker]
    gpus = "all"
    privileged = true
    volumes = ["/cache", "/usr/local/nvidia:/usr/local/nvidia:ro"]
"""

External template file#

[runners.gpu]
config_template_file = "runners/gpu-config.toml.tpl"

The template file uses the same Go text/template syntax. See Runner config templates for the full list of template variables.

Default runner templates#

The default runner ([runner]) can also use config_template to customize its config.toml. This is useful when you need to change runner-level settings globally without defining named runners:

# .glciconfig.toml

[runner]
config_template = """
[[runners]]
  [runners.docker]
    privileged = true
    network_mode = "host"
    shm_size = 2147483648
"""

When the default runner has a config_template, it gets its own per-project container (separate from the shared runner).

Multiple named runners#

You can define as many named runners as needed:

# .glciconfig.toml

[runners.gpu]
config_template = """
[[runners]]
  [runners.docker]
    gpus = "all"
    privileged = true
"""

[runners.arm]
config_template = """
[[runners]]
  [runners.docker]
    platform = "linux/arm64"
"""

[runners.shell]
config_template = """
[[runners]]
  executor = "shell"
"""
# .gitlab-ci.yml

train:
  tags: [gpu]
  script: python train.py

build-arm:
  tags: [arm]
  script: make build

deploy:
  tags: [shell]
  script: ./deploy.sh

lint:
  # no tags — runs on the default runner
  script: make lint

Runner name rules#

Runner names must match [a-zA-Z0-9][a-zA-Z0-9_-]*:

Lifecycle#

Esc