Installation¶
Audience: Platform engineer
This is the operator reference for installing the
Gateway Manager Controller (GMC) with the shipped actions-gateway Helm
chart. For day-2 operations after install, see upgrade.md. For
the full end-to-end walkthrough that continues past the GMC install into the
GitHub App Secret and the first ActionsGateway CR, see
Getting Started.
The Helm chart installs the GMC and its cluster prerequisites only — CRDs,
RBAC, the validating webhook, the namespace-psa-guard and
gmc-tenant-resource-guard admission policies, and NetworkPolicies. Per-tenant Actions Gateway Controller (AGC) instances and
egress proxy pools are not chart resources; the GMC provisions them at
runtime from each tenant's ActionsGateway CR. The chart is the sole install
path — there is no kustomize overlay; the plain-YAML files under cmd/gmc/config/
are the controller-gen codegen + test substrate, not an install vehicle. For the
full chart reference (every value, the templates it renders, offline validation),
see the chart README.
Prerequisites¶
- Kubernetes >= 1.30 — the GMC's
namespace-psa-guardandgmc-tenant-resource-guardpolicies need the GAValidatingAdmissionPolicyAPI. - Node architecture:
linux/amd64orlinux/arm64. Published images are multi-arch — one pinned digest (the OCI index digest) serves both, so mixed amd64/arm64 (e.g. Graviton) node pools need no per-arch configuration. Other architectures are not published. - A CNI that enforces
NetworkPolicy(Calico, Cilium) for the egress/ingress isolation controls to take effect.kindnetdoes not enforce egress, so the tenant-isolation guarantees do not hold under it. - Webhook serving cert — choose one:
- cert-manager (the default,
certManager.enabled=true). Install cert-manager first; it issues and rotates the webhook serving cert. - Self-signed (
certManager.enabled=false). The chart generates a self-signed serving cert and wires the webhookcaBundleitself — no cert-manager dependency. Trade-off: the cert rotates on ahelm upgradethat cannot reuse the existingwebhook-server-certSecret; see the cert behavior notes in upgrade.md. - A GitHub App with a private key and installation ID. The chart does not
consume the App credential — it is referenced per tenant by the
ActionsGatewayCR you create after install (see Getting Started). You only need the App registered and installed before onboarding a tenant, not before installing the chart. - Image digests for the GMC, AGC, and proxy images (see Pin images by digest below).
Install¶
General availability —
v1.0.0. The chart is published, cosign-signed, and installable straight from the GHCR OCI registry. Pin--version 1.0.0(the chart version is the release tag without the leadingv). Newer patch releases publish as1.0.z; pin the version you have verified.
Install the published, signed chart straight from the registry — no source checkout needed:
helm install gag oci://ghcr.io/actions-gateway/charts/actions-gateway \
--version 1.0.0 \
--namespace gmc-system --create-namespace \
--set gmc.image.digest=sha256:<gmc> \
--set agc.image.digest=sha256:<agc> \
--set proxy.image.digest=sha256:<proxy>
Copy the three image digests from the release notes (the chart ships no baked-in digests — empty digests are the fail-closed secure default, so an unconfigured render is rejected). Verify the chart and image signatures before installing — see release.md § Verify the publish and security-operations.md § Image provenance.
Installing from a source checkout (dev/CI, or to install an unreleased chart) still works — substitute the local
charts/actions-gatewaypath for theoci://…ref in any command on this page:
gag is the Helm release name and gmc-system is the install namespace; both
are conventions you can change. Keep namePrefix at its default gmc unless
you are running two GMCs in one cluster — the operational docs and the
namespace-psa-guard / gmc-tenant-resource-guard policies match resources by
that prefix.
Pin images by digest¶
Digest pinning is enforced for all three images, at two layers. This is the secure default: a digest is immutable, so neither the controller nor a tenant gateway can ever run from a tag that was silently re-pointed.
- GMC image — enforced at render time.
helm install/helm upgrade/helm templatefail withgmc.image must be pinned by digest: set gmc.image.digest=sha256:<64 hex digits> …whengmc.image.digestis empty. See the troubleshooting runbook if you hit this. - AGC/proxy images — enforced at GMC startup. The GMC rejects floating
AGC_IMAGE/PROXY_IMAGEtags and crash-loops until the AGC and proxy images are pinned by digest.
Pin gmc.image.digest, agc.image.digest, and proxy.image.digest as shown
above.
For dev/test only, you can bypass the pin:
helm install gag charts/actions-gateway \
--namespace gmc-system --create-namespace \
--set allowFloatingImageTags=true \
--set gmc.image.tag=<tag> --set agc.image.tag=<tag> --set proxy.image.tag=<tag>
Do not set allowFloatingImageTags=true in production.
Without cert-manager¶
helm install gag oci://ghcr.io/actions-gateway/charts/actions-gateway \
--version 1.0.0 \
--namespace gmc-system --create-namespace \
--set certManager.enabled=false \
--set gmc.image.digest=sha256:<gmc> \
--set agc.image.digest=sha256:<agc> \
--set proxy.image.digest=sha256:<proxy>
The chart generates a self-signed webhook serving cert and wires the caBundle
itself. Review the rotation trade-off in
Prerequisites before choosing this path.
Key values an operator sets¶
The chart ships secure, HA defaults; most installs only set the three image digests. The knobs an operator is most likely to override:
| Key | Default | When you change it |
|---|---|---|
gmc.image.digest / agc.image.digest / proxy.image.digest |
"" |
Always — pin all three by digest. The chart refuses to render while gmc.image.digest is empty. |
allowFloatingImageTags |
false |
Dev/test only — opt out of digest pinning (render-time GMC check and startup-time AGC/proxy check). |
certManager.enabled |
true |
Set false to use the self-signed webhook cert instead of cert-manager. |
namePrefix |
gmc |
Only when running a second GMC in the same cluster. |
replicaCount |
2 |
Lower to 1 only in dev; production wants HA + leader election. |
metrics.serviceMonitor.enabled |
false |
Set true if you run Prometheus Operator and want a ServiceMonitor. |
networkPolicy.enabled |
true |
Leave on; needs an enforcing CNI (see prerequisites). |
A values.schema.json validates these at install/lint time (digest format,
enum values, etc.). The full reference — every value with its default and
description — lives in the
chart README; this table is
only the common subset, not a duplicate.
Verify a healthy install¶
# 1. Both GMC replicas are Running and Ready (HA default replicaCount=2).
kubectl get deploy -n gmc-system gmc-controller-manager
# Expected: READY 2/2
kubectl get pods -n gmc-system -l app.kubernetes.io/name=actions-gateway
# Expected: 2 pods, all Running
# 2. A leader has been elected (the lease holder is the active replica).
kubectl get lease -n gmc-system
# Expected: a lease whose HOLDER is one of the GMC pods
# 3. Both CRDs are installed and Established.
kubectl get crd actionsgateways.actions-gateway.github.com \
runnergroups.actions-gateway.github.com
kubectl wait --for=condition=Established \
crd/actionsgateways.actions-gateway.github.com \
crd/runnergroups.actions-gateway.github.com
# 4. The validating webhook and both admission policies are present.
# (Resource names carry the chart namePrefix, default "gmc-".)
kubectl get validatingwebhookconfiguration | grep actions-gateway
kubectl get validatingadmissionpolicy gmc-namespace-psa-guard gmc-tenant-resource-guard
# 5. No errors in the GMC manager logs.
kubectl logs -n gmc-system deploy/gmc-controller-manager --tail=30
# Look for: "Starting workers" / "successfully acquired lease"; no repeated
# "AGC_IMAGE must be pinned by digest" (that means a floating-tag crash-loop).
If the GMC pods are in CrashLoopBackOff with an image-pinning error, you
installed with a floating AGC/proxy tag and without allowFloatingImageTags —
re-run the install with the three digests pinned (see
Pin images by digest). For other failure modes, see
troubleshooting.md.
Once the GMC is healthy, continue with Getting Started
to create the GitHub App Secret and the first ActionsGateway CR, or follow the
Tenant Onboarding Checklist to bring up a tenant.
Uninstall¶
The two CRDs ship as templates carrying helm.sh/resource-policy: keep, so
helm uninstall preserves the CRDs and every tenant's ActionsGateway /
RunnerGroup object rather than cascade-deleting them — uninstalling the GMC
does not tear down running tenant gateways. To fully remove them, delete the
tenant CRs first, then the CRDs explicitly:
# Only after confirming no tenant still needs their gateways:
kubectl delete actionsgateway --all --all-namespaces
kubectl delete crd actionsgateways.actions-gateway.github.com \
runnergroups.actions-gateway.github.com
The install namespace (gmc-system) is left in place if you created it with
--create-namespace; remove it with kubectl delete namespace gmc-system once
empty.
Next steps¶
- Getting Started — the full walkthrough from here:
GitHub App Secret,
ActionsGatewayCR, first job. - Tenant Onboarding Checklist — onboard a tenant team.
- upgrade.md — day-2
helm upgrade/helm rollback, CRD field changes, and the per-component upgrade procedures.