GitHub Actions runners
Run GitHub Actions jobs on Composal. Choose VM or sandbox runners, use the included tools, or preload your own Docker image.
Contents
Use the included tools
Composal runners include Node 24, AWS CLI v2 and GitHub CLI (gh).
Use them directly in your workflow steps.
actions/setup-node or your project's tool manager can select another Node
version.
Set up runner access
Install Vex 1.17.90 or newer to manage runners. Sign in and check the pools and images available to your organization:
curl -fsSL https://dl.composal.ai/install-vex -o /tmp/install-vex.sh
sh /tmp/install-vex.sh
vex login
vex --org acme runner github list
vex --org acme runner images list
vex agent-help
Your organization needs GitHub Actions runner access enabled and a GitHub App connection with access to the repository. Organization owners and administrators can configure images and pools. A pool serves one exact repository/label pair.
Choose a VM or sandbox
| Workflow label | Runtime | Choose for |
|---|---|---|
composal-vm-x64-4x | VM | Docker builds, container actions and service containers |
composal-sandbox-x64-4x | Sandbox | Shell and JavaScript actions, lint and tests without Docker |
composal-x64-4x | VM | Existing workflows; keeps VM behavior |
Each label family offers 2x, 4x, 8x and 16x sizes, with 2/4/8/16 CPU cores and 4/8/16/32 GiB RAM. Sandboxes do not run a Docker daemon. Use a VM for container actions, service containers and Docker builds.
Configure a runner pool
Configure a pool to use the standard tools:
vex --org acme runner github configure acme/monorepo \
--label composal-sandbox-x64-4x --default-image --max-concurrency 8
Then select that exact label in GitHub Actions:
jobs:
check:
runs-on: composal-sandbox-x64-4x
steps:
- uses: actions/checkout@v7
- run: node --version && aws --version && gh --version
Mount dependency caches
Mount persistent storage at a package cache directory with a stable key:
- uses: composalai/disk-volume@v1.2.0
with:
key: npm-store-v1
path: ~/.npm
- run: npm ci
Package managers use the mounted directory in place. The post step flushes
writes; there is no archive restore, copy-back or automatic cache cleanup.
The checkout, workspace and .git stay on local runner disk.
Keys are scoped to the GitHub installation and repository. Jobs with the same key share a writable cache across branches and runner sizes, including pull requests and failed jobs. Use download stores with package integrity checks, such as npm, pnpm and Cargo caches. Keep credentials and build outputs out of these directories. Choose separate keys for tools that require exclusive access.
The action accepts an empty absolute, workspace-relative or ~/ path, with up
to five mounts per job. cache-hit: true means the directory exists; the package
manager still installs missing dependencies. The first run after this storage
update starts cold.
Preload your own tools
For additional tools or pinned dependencies, write a linux/amd64 Ubuntu 24.04 Dockerfile with Node 22 or newer on PATH. Custom images keep their own Node version. Keep credentials out of image layers. For example:
FROM node:24-bookworm-slim AS node
FROM ubuntu:24.04
COPY --from=node /usr/local/ /usr/local/
RUN apt-get update && apt-get install -y ca-certificates curl git gh jq
Build and push it to your registry. Register the immutable digest printed by the push, replacing the placeholder with its real 64-character SHA-256:
docker buildx build --platform linux/amd64 \
--tag ghcr.io/acme/actions-tools:v1 --push .
vex --org acme runner images create tools-v1 \
--image ghcr.io/acme/actions-tools@sha256:<64-hex-digest> --wait
vex --org acme runner github configure acme/monorepo \
--label composal-sandbox-x64-4x --image tools-v1
Composal prepares the image once, adding the Actions runner and its supporting
tools. Preparation moves through pending and building, then ends at ready
or failed. New runners reuse the prepared image. Composal replaces CMD and
ENTRYPOINT, so put permanent setup in Dockerfile RUN instructions.
Pull from a private registry
Private registries use --registry-secret RUNNER_REGISTRY. This names an active
organization secret exposed to CI whose JSON value contains exactly
REGISTRY_USERNAME and REGISTRY_PASSWORD, both nonempty strings. Store the
value using secret management with stdin or a private file. Composal uses these credentials
to pull the image; it does not add them to workflow environments. Registration does not grant
registry access.
Update tools or restore the defaults
Inspect preparation and retry a failed build:
vex --org acme runner images get tools-v1 --json
vex --org acme runner images prepare tools-v1
vex --org acme runner images wait tools-v1 --json
Ready images are immutable. Publish a new digest and image name to update tools.
Images are scoped to their organization. Switching a pool affects new runners;
running jobs finish on their original image. A pool waits for its selected image
to become ready. Verify a real GitHub job receives a composal-gh-* runner,
prints the expected tool versions, and reaches a terminal result.
Use --default-image to restore the standard toolchain. Omit both image flags
to retain the current selection. Configuring a label does not rewrite workflows
or disable other pools; each pool has its own concurrency limit.