Skip to content

Configuration

GitLab Runner config.toml

Add the executor hooks to your runner configuration:

concurrent = 2

[[runners]]
  name = "jeballto-custom"
  url = "https://gitlab.example.com"
  token = "REDACTED"
  executor = "custom"
  shell = "bash"
  limit = 2
  request_concurrency = 2
  environment = [
    "JEBALLTO_BASE_URL=http://127.0.0.1:8011/v1"
  ]

  [runners.custom]
    config_exec = "/usr/local/bin/jeballto-gitlab-executor"
    config_args = ["config"]

    prepare_exec = "/usr/local/bin/jeballto-gitlab-executor"
    prepare_args = ["prepare"]

    run_exec = "/usr/local/bin/jeballto-gitlab-executor"
    run_args = ["run"]

    cleanup_exec = "/usr/local/bin/jeballto-gitlab-executor"
    cleanup_args = ["cleanup"]

    config_exec_timeout = 60
    prepare_exec_timeout = 9000
    cleanup_exec_timeout = 300

The repo also contains the same sample in examples/config.toml.snippet.

Runner concurrency

One Jeballto host has two VM slots. GitLab Runner must enforce that at job pickup time:

  • set top-level concurrent = 2 for a runner process dedicated to this host
  • set limit = 2 on the Jeballto [[runners]] entry
  • set request_concurrency = 2 so the runner asks for at most two jobs for that entry
  • run only one GitLab Runner service/process for the host, unless the total limits across all entries still add up to two

Executor capacity waiting is only a recovery path for races, stale VMs, or external VM usage. It cannot stop GitLab from assigning a job after GitLab Runner has already accepted it. If three or four jobs are shown as picked, inspect every active config.toml and every runner process. Common causes are duplicate runner entries using the same token, a system runner plus a user runner both running, or limit placed under [runners.custom] instead of directly under [[runners]].

Core environment variables

Variable Default Purpose
JEBALLTO_BASE_URL http://127.0.0.1:8011/v1 Jeballto API base URL
JEBALLTO_TOKEN auto-detected API bearer token
JEBALLTO_TOKEN_FILE ~/Library/Application Support/Jeballto/config.json Token file fallback
JEBALLTO_DEFAULT_IMAGE unset Default OCI image when jobs do not provide one

The executor defaults to 127.0.0.1 because same-host deployments are the common case. The Jeballto Agent itself binds to 0.0.0.0:8011 by default unless api.host is changed.

VM sizing

Set sizing variables on the GitLab Runner host, for example in the runner config.toml environment = [...] array or in the service environment that launches gitlab-runner. Jobs may also set the same variables in .gitlab-ci.yml; GitLab exposes them to custom executor hooks as CUSTOM_ENV_JEBALLTO_*, and the executor reads both forms.

[[runners]]
  name = "jeballto-macos"
  executor = "custom"
  environment = [
    "JEBALLTO_VM_CPU_COUNT=6",
    "JEBALLTO_VM_MEMORY_SIZE=12884901888",
    "JEBALLTO_VM_DISK_SIZE=274877906944",
    "JEBALLTO_VM_LIFETIME_SECONDS=7200"
  ]

Plain JEBALLTO_* values take precedence over CUSTOM_ENV_JEBALLTO_* values. That lets host configuration define hard defaults while still allowing job-level overrides when the host does not set a plain value.

Variable Default Purpose
JEBALLTO_VM_NAME_PREFIX gl Prefix for deterministic VM names
JEBALLTO_VM_LIFETIME_SECONDS 0 Max VM lifetime in seconds, 0 means no limit
JEBALLTO_VM_CPU_COUNT 0 Requested vCPU count, 0 keeps the image default
JEBALLTO_VM_MEMORY_SIZE 0 Requested memory in bytes, 0 keeps the image default
JEBALLTO_VM_DISK_SIZE 0 Requested disk size in bytes, 0 keeps the image default

Resource values are only applied when they are greater than 0. A missing value or 0 sends no resource override, so the VM keeps the CPU, memory, and disk from the image. When an image is present and any resource override is greater than 0, resource updates happen after VM creation and before the VM starts because the Jeballto API does not accept image and resource overrides in the same create call.

JEBALLTO_VM_LIFETIME_SECONDS is passed to Jeballto as lifetimeSeconds. Positive values must be between 1 and 604800 seconds.

Use lifetime as a CI/CD safety guard. Set it slightly higher than the GitLab job timeout because the VM still needs time to boot, become reachable over SSH, and start the job after creation. Image pull happens before VM creation, so it does not need to be included in this buffer. For example, if jobs can run for 60 minutes, use a VM lifetime such as 3900 or 4200 seconds.

SSH configuration

Variable Default Purpose
JEBALLTO_SSH_USER admin SSH username inside the VM
JEBALLTO_VM_PASSWORD admin SSH password
JEBALLTO_VM_PASSWORD_ENV JEBALLTO_VM_PASSWORD Env var name that stores the password
JEBALLTO_SSH_CONNECT_TIMEOUT 20s Per-connection timeout for OpenSSH

Image policy

Variable Default Purpose
JEBALLTO_ALLOW_JOB_IMAGE_OVERRIDE true Allow image: in .gitlab-ci.yml
JEBALLTO_IMAGE_ALLOWLIST unset Comma-separated glob allowlist

See Image Policy for the full resolution order.

Timeouts

Variable Default Purpose
JEBALLTO_PREPARE_TIMEOUT 150m Full prepare budget, including image pull
JEBALLTO_IMAGE_PULL_TIMEOUT 120m Time to pull a missing image
JEBALLTO_IMAGE_PULL_LOCK_TIMEOUT 130m Time to wait for another job pulling the same image
JEBALLTO_STATE_WAIT_TIMEOUT 10m Time to wait for RUNNING
JEBALLTO_SSH_WAIT_TIMEOUT 5m Time to wait for SSH readiness
JEBALLTO_PROBE_TIMEOUT 90s Toolchain readiness probe
JEBALLTO_STOP_TIMEOUT 2m Stop timeout during cleanup
JEBALLTO_DELETE_TIMEOUT 2m Delete timeout during cleanup

Retry and local state

Variable Default Purpose
JEBALLTO_RETRY_MAX_ATTEMPTS 6 Retries for transient API failures
JEBALLTO_RETRY_INITIAL_BACKOFF 1s Initial retry delay
JEBALLTO_RETRY_MAX_BACKOFF 20s Backoff cap
JEBALLTO_STATE_ROOT ~/.cache/jeballto-gitlab-executor/jobs Job state and lock file root
JEBALLTO_BUILDS_BASE_DIR /tmp/builds Build directory inside the VM
JEBALLTO_CACHE_BASE_DIR /tmp/cache Cache directory inside the VM

For a first host, start with:

  • one default image
  • positive JEBALLTO_VM_LIFETIME_SECONDS slightly higher than your GitLab job timeout
  • job image overrides enabled only if you also define an allowlist
  • default retry settings
  • default timeouts
  • explicit SSH credentials instead of relying on image defaults

Validation checklist

Before running the first real pipeline:

  1. confirm the Jeballto Agent health endpoint responds
  2. confirm the token is available either via env var or config file
  3. confirm the image exists or can be pulled by the agent
  4. confirm the VM image contains bash, git, and gitlab-runner
  5. confirm the GitLab Runner process can execute the hook binary