When hosted runners aren’t enough

GitHub Actions’ built-in runners cover Windows, Linux, and macOS, but custom workloads often need more: larger memory or CPU pools, GPUs or TPUs, ARM architectures, access to on-premises resources, or tools that can only live inside an organization’s security perimeter. For those cases, self-hosted runners give teams full control over the execution environment. The runners can be physical servers, VMs, or containers, running in the cloud, on-premises, or across both.

Google Cloud offers several distinct patterns for running self-hosted GitHub Actions runners. Note that these setups are experimental and not officially supported by GitHub. Also, GitHub recommends against using self-hosted runners on public repositories for security reasons.

Ephemeral runners with App Engine

The first pattern builds on App Engine’s container support to run self-hosted runners that can scale automatically with demand. A custom container image installs the GitHub Actions runner, and a startup script registers it against the desired repository or organization. The app.yaml configuration enables CPU-based autoscaling, and serverless VPC access can connect the runners to other resources inside your network.

This approach has some limitations worth noting. App Engine doesn’t expose custom hardware like GPUs or TPUs, and it can’t run on-premises. Since App Engine already runs inside a container, Docker-based actions — anything that requires the Docker daemon — won’t work in this setup.

Dedicated VMs on Compute Engine

When you need specific machine shapes or accelerated hardware, Compute Engine lets you build runners that match your exact workflow requirements. Managed Instance Groups provide a single management view across these VMs, plus autoscaling based on usage. For authentication, VMs can rely on Application Default Credentials through their attached service account, avoiding the need to store and rotate service account keys.

An example Managed Instance Groups runner setup is available at https://github.com/bharathkkb/gh-runners/tree/master/gce.

Kubernetes runners with GKE and Workload Identity

Google Kubernetes Engine is a standard Kubernetes installation, so any existing community pattern for deploying GitHub Actions runners on Kubernetes works there. Teams already on Kubernetes can get additional benefit from GKE’s Workload Identity feature, which binds a Kubernetes Service Account to a Google Service Account. The runner pods authenticate to Google Cloud APIs with short-lived credentials rather than service account keys, which are typically valid for ten years and require manual rotation.

An example GKE runner with Workload Identity is at https://github.com/bharathkkb/gh-runners/tree/master/gke, with a sample workflow at https://github.com/bharathkkb/gh-runners/tree/master/example-workflow.

Hybrid runners with Anthos

Anthos extends the GKE experience to infrastructure you control, including on-premises environments. The full reference implementation is in the self-hosted-runners-anthos repository. The provisioning scripts create the Google Cloud project, enable all needed services, and spin up an Anthos-managed GKE cluster. Kubernetes secrets hold the TOKEN that lets each runner pod register and deregister itself, plus a GITHUB_REPO variable that determines where runners are available.

The Dockerfile builds on a general-purpose Ubuntu image. After installing the runner software, the setup allocates pods for two types of jobs: a test job that builds on pull requests, and a deploy job that pushes to Google Container Registry, then uses kustomize to apply the updated manifest back to the Anthos cluster.

Container builds are possible because the project runs a Docker-in-Docker sidecar pod. That flexibility comes at a cost: the sidecar requires a privileged security context and extends the trust boundary across the entire cluster. Teams that don’t need containerized actions should remove the sidecar. Scaling down replicas mid-build is also discouraged, since selecting only idle runners isn’t feasible yet. Off-peak scaling — down late at night, back up before the workday — is a safer alternative.