Skip to content

Repository files navigation

Cloudflare Containers GitHub Actions Runner

Run GitHub Actions jobs in fresh, disposable Cloudflare Containers. A signed GitHub App workflow_job webhook asks the Worker to provision a repository-scoped just-in-time runner. The Worker starts a disposable Container with GitHub's JIT runner configuration; after it completes its one assigned job, GitHub automatically deregisters it.

Quick start

With Node.js 20.19+ (or 22.13+), a GitHub browser session, and Wrangler authentication for a Workers Paid Cloudflare account with Containers enabled:

npx -y cloudflare-github-actions-runner@latest setup

The interactive CLI deploys the runner pool and guides you through selecting its GitHub account or organization, creating its GitHub App, and optional private R2 cache setup. Docker and a local checkout are not needed.

Choose a runner

Use one label directly in a workflow:

runs-on label Machine type vCPU Memory Disk
cloudflare-lite linux/amd64 1/16 256 MiB 2 GB
cloudflare-basic linux/amd64 1/4 1 GiB 4 GB
cloudflare-standard-1 linux/amd64 1/2 4 GiB 8 GB
cloudflare-standard-2 linux/amd64 1 6 GiB 12 GB
cloudflare-standard-3 linux/amd64 2 8 GiB 16 GB
cloudflare-ubuntu-latest linux/amd64 2 8 GiB 16 GB
cloudflare-standard-4 linux/amd64 4 12 GiB 20 GB

All profiles use the same managed Ubuntu 24.04 runner image. Resource values come from the Cloudflare Containers instance types.

For a custom machine, quote the single label:

runs-on: "cloudflare-vcpu:2-memory_mib:6144-disk_mb:12000"

Custom values must use 1–4 whole vCPUs, up to 12,288 MiB memory and 20,000 MB disk; memory must be at least 3,072 MiB per vCPU and disk no more than 2 GB per GiB memory. Invalid requests fail visibly in Set up runner before any workflow step starts.

What setup does

The interactive setup:

  1. Verifies your Cloudflare user, account, Containers access, and Docker-free remote builder support.
  2. Lets you select the Cloudflare account that owns and bills for the shared runner pool.
  3. Deploys the Worker, runner profiles, and managed runner image.
  4. Maps the selected Cloudflare account to one GitHub personal account or organization, then creates or reuses that pool's GitHub App. Install it for All repositories in that selected account or organization.
  5. Optionally creates a private R2 cache bucket (default: cloudflare-github-actions-runner-cache) with a FIFO quota (default: 100 GB).

One Cloudflare runner pool serves exactly one GitHub account or organization. Run setup again to create a separate mapping for another Cloudflare account. An App installation covers all selected repositories in that target, including future repositories. It needs Actions: Read, Administration: Write, and Contents: Read, plus the workflow_job and push webhook events. App keys, installation tokens, and Cloudflare credentials stay out of runner Containers.

The managed runner image is built from this repository's public main branch, so setup does not need a second App installation on biw just to read it. Setup builds the current image; after a published runner-image update, rerun setup to roll that update into your pool. Keep this repository's main protected.

Workflow

jobs:
  ci:
    runs-on: cloudflare-ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v6
      - run: corepack enable
      - run: pnpm install --frozen-lockfile
      - run: pnpm run check

Use actions/cache normally. JavaScript actions, including actions/cache and actions/setup-node, are transparently backed by the private R2 bucket; artifact uploads and job results continue to use GitHub. PR caches are scoped to their merge ref and can fall back to the default-branch cache, matching GitHub Actions behavior.

This repository's CI admission policy

This repository takes its CI definition from main with the pull_request_target event. Before it checks out a pull request's merge ref or starts a Cloudflare runner, it checks the pull-request author's repository permission. Administrators proceed immediately. Everyone else waits at the cloudflare-ci-approval protected GitHub environment for an administrator to approve the run. The job receives only a read-only GITHUB_TOKEN; pull-request-target runs also have read-only access to the shared R2 cache.

The protected environment must list the repository's current administrators as required reviewers, with self-review disabled. CI fails closed before Cloudflare provisioning if that rule is missing. GitHub makes required reviewers available on public repositories for all current plans; while this repository remains private without that entitlement, a non-admin PR is therefore blocked rather than run. Keep main protected so the gate itself remains trusted.

Operations

  • From a checkout, use pnpm run deploy for normal updates, or pnpm run deploy:dry-run to inspect safely. Neither requires local Docker.
  • The account-scoped scheduler queues jobs only when the Cloudflare account lacks available vCPU, memory, or disk. It retains idle application capacity without keeping instances alive or incurring runtime charges.
  • A new custom size may wait while Cloudflare rolls out an idle custom runner slot. It reuses the shared image; it does not build another image.
  • Containers run the job compute; GitHub provides scheduling and logs. Runners are disposable, have no Cloudflare credentials, and cannot use sudo. Docker-based Actions are outside this shell/JavaScript POC.
  • Every runner records one-second CPU, memory, and writable-disk samples to D1. Use cf-resource-mark "phase" in workflow steps and cf-resource-trace summary to add a job summary. The included workflow uploads the CSV trace as a seven-day artifact.
  • Machine labels are currently trusted workflow input. Per-repository quotas and spending controls are future work.

Query the persisted metrics for a GitHub job:

CLOUDFLARE_ACCOUNT_ID=<account-id> pnpm run resource-traces -- \
  --command="SELECT sample_elapsed_seconds, phase, cpu_cores_avg, memory_current_bytes, root_disk_delta_bytes FROM resource_trace_samples WHERE job_id = '<github-job-id>' ORDER BY sample_elapsed_seconds"

License

MIT

About

Run GitHub Actions jobs in Cloudflare Containers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages