Runner groups
A runner group starts a fresh runner for each run. Set one up with GitHub Actions or run one in your Kubernetes cluster.
GitHub Actions
GantryCD can dispatch a workflow in a GitHub repository. GitHub then provides the runner.
- Create a GitHub App with Actions: read and write repository access.
- Install the App on the repository that will hold the workflow.
- Expand the workflow template below and copy it to
.github/workflows/gantrycd-runner.yamlin that repository. - In GantryCD, open Runner groups → Create Runner Group and choose GitHub Actions.
- Enter:
- the repository as
owner/name; - the workflow file and ref;
- the App ID and private key;
- the maximum number of concurrent runs.
- the repository as
Workflow template
name: GantryCD Runner
run-name: gantrycd-${{ inputs.correlation-id }}
on:
workflow_dispatch:
inputs:
assignment-token:
required: true
gantrycd-url:
required: true
correlation-id:
required: true
runner-version:
required: true
env:
TENV_VERSION: v4.12.2
jobs:
run:
# Change this label to choose another GitHub runner.
runs-on: ubuntu-slim
timeout-minutes: 75
steps:
- name: Resolve architecture and tool paths
env:
HOST_ARCH: ${{ runner.arch }}
run: |
set -euo pipefail
case "${HOST_ARCH}" in
X64) arch=amd64; tenv_arch=x86_64 ;;
ARM64) arch=arm64; tenv_arch=arm64 ;;
*) echo "unsupported runner.arch: ${HOST_ARCH}" >&2; exit 1 ;;
esac
TOOLS_DIR="${HOME}/.cache/gantrycd-tools"
mkdir -p "${TOOLS_DIR}/tenv"
printf '%s\n' "${TOOLS_DIR}/tenv" >> "${GITHUB_PATH}"
{
echo "ARCH=${arch}"
echo "TENV_ARCH=${tenv_arch}"
echo "TOOLS_DIR=${TOOLS_DIR}"
echo "TENV_ROOT=${HOME}/.tenv"
} >> "${GITHUB_ENV}"
- name: Install cosign
run: |
set -euo pipefail
curl -fsSL -o cosign \
"https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-${ARCH}"
sudo install -m 0755 cosign /usr/local/bin/cosign
rm cosign
- name: Download runner binary
env:
RUNNER_VERSION: ${{ inputs.runner-version }}
run: |
set -euo pipefail
curl -fsSL -o runner.tar.gz \
"https://artifacts.gantrycd.io/releases/${RUNNER_VERSION}/runner-${RUNNER_VERSION}-linux-${ARCH}.tar.gz"
tar -xzf runner.tar.gz
chmod +x runner
- name: Cache the OpenTofu runtime
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.cache/gantrycd-tools/tenv
~/.tenv
key: ${{ runner.os }}-${{ runner.arch }}-tofu-runtime-${{ env.TENV_VERSION }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-tofu-runtime-${{ env.TENV_VERSION }}-
- name: Install tenv
run: |
set -euo pipefail
if [ -x "${TOOLS_DIR}/tenv/tenv" ]; then
echo "tenv ${TENV_VERSION} restored from cache"
else
curl -fsSL "https://github.com/tofuutils/tenv/releases/download/${TENV_VERSION}/tenv_${TENV_VERSION}_Linux_${TENV_ARCH}.tar.gz" \
| tar -xz -C "${TOOLS_DIR}/tenv"
fi
command -v tenv
- name: Run the ephemeral runner
env:
BACKEND_URL: ${{ inputs.gantrycd-url }}
EPHEMERAL_RUNNER_JWT: ${{ inputs.assignment-token }}
run: ./runner
The template accepts the assignment from GantryCD, downloads the matching
runner version, and starts it. Keep its four workflow inputs and its run-name
unchanged.
GitHub Actions receives no runner spec overrides from a stack. The runner label
(runs-on), container image, and other compute options are set in the workflow.
You can reuse the GitHub App from your repository integration. The App ID and private key still need to be added to the runner group.
Self-hosted with Helm
The runner group Helm chart runs a launcher in your cluster. The launcher creates one short-lived Kubernetes Pod for each run.
First, open Runner groups → Create Runner Group, choose Self-hosted, and save the group ID and private key. The private key is shown only once.
Create a namespace and store the key:
kubectl create namespace acme
kubectl -n acme create secret generic acme-runners-key \
--from-file=private-key=/path/to/private-key.pem
Install one runner group in that namespace:
helm install acme-runners \
oci://ghcr.io/gantrycd/helm/gantrycd-runner-group-kubernetes \
--version vX.Y.Z \
--namespace acme \
--set groupID=<group-id> \
--set backendURL=http://gantrycd.gantrycd.svc:8080 \
--set privateKey.existingSecret=acme-runners-key
Use a values file for shared settings:
maxConcurrent: 4
ephemeralRunner:
serviceAccount: gantrycd-runner
serviceAccountCreate: true
cpu: "1"
memory: 1Gi
cpu and memory set both the request and limit for every runner Pod. A stack
can override each value separately.
The backend URL must be reachable from the cluster. The service account is the identity used by the short-lived runner Pods, so attach the cloud access they need to it.
View all chart values for your version:
helm show values \
oci://ghcr.io/gantrycd/helm/gantrycd-runner-group-kubernetes \
--version vX.Y.Z
Use runner group selectors to route stacks and pass runner spec overrides supported by the selected group.