Multi-tenant runner platform for Kubernetes
Self-hosted GitHub Actions with zero idle compute¶
An Actions Runner Controller (ARC) alternative for multi-tenant Kubernetes. Free up GPU nodes the moment a job finishes, keep critical jobs scheduling even on a full cluster, and let tenants self-manage runners under safe per-tenant quotas.
Get started Watch the demo Why GAG? View on GitHub
Drop-in for your existing setup — jobs target the same runner labels, so nothing in your .github/workflows changes.
What GAG gives you¶
Most of these ladder up to one outcome — lower cost: no idle GPUs, fewer always-on resources, and guaranteed throughput instead of blocked critical jobs. Estimate your savings vs ARC →
-
Tenant self-service under quotas
Quotas you can safely enforce:
- Platform-owned quota cap
- Blocked jobs auto-recover
- Zero manual reruns
- Tenants manage their runners
-
No blocked critical jobs
Reserve capacity for key runners:
- Reserve N slots per runner type
- CPU tests can't starve GPU jobs
- Critical tests always schedule
-
No idle GPUs
Pods live only for the job:
- Created on acquire
- Deleted on completion
- GPU freed the instant a job ends
- Scale-to-zero by default
-
Isolated egress IPs
Each tenant's own proxy pool:
- Allow-list runners on GitHub Enterprise Managed Users (EMU)
- No shared cluster allow-list
- Flagged tenants stay isolated
- v2: proxy optional
-
Lower listener overhead
Listeners are goroutines, not pods:
- ~60 KiB per runner group
- One shared pod per tenant
- 600 KiB vs 2.5 GiB for ten groups
-
Per-tenant observability
Scoped visibility, no cluster access:
- Prometheus per tenant + group
- Grafana dashboards + alerts, as code
- Job counts in
kubectl get - K8s Events on job transitions
-
Shared runner templates v2
Define once, reference by name:
RunnerTemplateper many sets- Platform
ClusterRunnerTemplate - Identical templates collapse
- Migrate v1→v2 with
gag-migrate
-
Secure by default
Hardening reconciled by default:
baselinePod Security Admission (PSA) per namespace- Default-deny NetworkPolicies
- Credentials never in env vars
- Signed images + Software Bill of Materials (SBOM) + SLSA
-
Tenant runner self-service v2
Self-managed runners, one setup:
- Self-serve
ActionsGatewayCRs - Tune
maxRunnersper group - Multiple gateways per namespace
- No platform ticket per change
- Self-serve
Who GAG is for¶
GAG targets a specific audience: teams that must self-host runners and run them for many tenants on one cluster. If that's you, here's the value per segment.
-
Platform & developer-experience teams
Multi-tenant CI on a shared cluster:
- Enforce a per-team quota without stranding jobs
- Tenants self-serve from one
ActionsGateway - No ticket queue for every runner change
-
Orgs that must self-host
Driven by a hard constraint, not preference:
- Compliance or data-residency requirements
- EMU or firewalled-service IP allow-lists
- Per-tenant egress IPs you allow-list directly
-
GPU / ML platform teams
Done paying for accelerators between jobs:
- Workers scale to zero — no idle GPU
- GPU nodes return to the scheduler on completion
- Priority tiers keep critical GPU jobs scheduling
Not your setup? If you're happy running on a vendor's infrastructure, a managed-SaaS runner is the better fit. GAG competes with Actions Runner Controller (ARC) for self-hosted, multi-tenant clusters — not on raw build speed.
How it fits together¶
A four-tier system: a cluster-scoped manager gives each tenant an isolated gateway from its ActionsGateway. Jobs are acquired with the same single-acquirer runner-scale-set protocol ARC uses — the shipped default — so GAG is a strict superset of ARC's model, not a different-architecture trade-off.
Read the architecture overview for the full breakdown, jump to why GAG over ARC, or see the public roadmap for what's shipped and what's next.