Installation¶
This page installs the operator and its CRDs. It does not create a Garage cluster; use the quickstart after the operator is ready.
Requirements¶
- Kubernetes
1.25+for ordinary workloads;1.27+for node-local pools. - Helm
3.8+. - Garage
v2.0.0+; the default image is the tested Garagev2.4.1digest. - cert-manager for the admission and conversion webhooks. The chart enables webhooks by default.
The operator must be allowed to watch the namespaces in which its GarageCluster, GarageNode, bucket, key, and token resources live. A cluster-scoped installation is required for zoneFrom and node-local pools.
Install the latest published chart¶
helm install garage-operator \
oci://ghcr.io/rajsinghtech/charts/garage-operator \
--namespace garage-operator-system \
--create-namespace
Pin a version in production:
helm install garage-operator \
oci://ghcr.io/rajsinghtech/charts/garage-operator \
--version 0.8.2 \
--namespace garage-operator-system \
--create-namespace
The chart installs CRDs and keeps them on uninstall by default. It enables:
- conversion and validating webhooks;
- leader election;
- an authenticated HTTPS metrics endpoint and metrics Service;
- restrictive operator pod security defaults.
Do not disable webhooks for production storage
webhooks.enabled=false removes conversion and admission safety boundaries. It is limited to local development or simple v1beta2-only EmptyDir experiments. It is not supported for node-local pools, controller-managed persistent claims, PVC-backed rollout/recovery, or prepared storage deletion.
Verify the installation¶
kubectl -n garage-operator-system rollout status \
deployment/garage-operator-controller-manager --timeout=180s
kubectl get crd \
garageclusters.garage.rajsingh.info \
garagebuckets.garage.rajsingh.info \
garagekeys.garage.rajsingh.info \
garagenodes.garage.rajsingh.info
Check the chart's rendered configuration before upgrading an existing release:
helm get values garage-operator \
--namespace garage-operator-system --all
helm status garage-operator --namespace garage-operator-system
Namespace-scoped operation¶
Set watchNamespaces when the operator should reconcile only selected namespaces. The release namespace is always included. CRDs remain cluster-scoped and must still be installed by a cluster administrator.
helm upgrade --install garage-operator \
oci://ghcr.io/rajsinghtech/charts/garage-operator \
--namespace garage-operator-system \
--create-namespace \
--set 'watchNamespaces={storage,team-a,team-b}'
Use the chart's cosi.namespace when enabling COSI in a separate namespace; authorize that namespace with a GarageReferenceGrant in each target cluster namespace.
Raw manifests (install.yaml / kustomize): website exposure flags¶
The Helm chart turns on website exposure with ingress.enabled and
gatewayAPI.enabled. The install.yaml release asset and the config/default
kustomize base have no templating layer and start the manager without
--enable-ingress and --enable-gateway-api, so a GarageBucket that sets
spec.websiteExposure.ingress (or .gateway) reports WebsiteExposed=False
with reason IngressDisabled (or GatewayAPIUnavailable) and no Ingress or
HTTPRoute is created.
install.yaml already carries the RBAC rules for both
networking.k8s.io/ingresses and gateway.networking.k8s.io/httproutes, so
adding the flag is all that is needed. Add only the flags you use. Gateway API
also needs its CRDs installed; the operator never installs them.
Patch the running Deployment (the manager is the first container):
kubectl -n garage-operator-system patch deployment garage-operator-controller-manager \
--type=json -p='[
{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--enable-ingress"},
{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--enable-gateway-api"}
]'
Or, equivalently, set the environment variables the flags read:
kubectl -n garage-operator-system set env deployment/garage-operator-controller-manager \
ENABLE_INGRESS=true ENABLE_GATEWAY_API=true
To keep the change in Git, patch the release manifest with kustomize:
# kustomization.yaml
resources:
- install.yaml # the release asset, downloaded
patches:
- target:
kind: Deployment
name: garage-operator-controller-manager
patch: |-
- op: add
path: /spec/template/spec/containers/0/args/-
value: --enable-ingress
- op: add
path: /spec/template/spec/containers/0/args/-
value: --enable-gateway-api
The Deployment rolls and the operator re-evaluates every bucket's
WebsiteExposed condition after the restart. A later kubectl apply of a
fresh install.yaml resets a patch made directly on the cluster, so prefer the
kustomize form for anything long-lived.
Private registries and immutable images¶
Use imagePullSecrets for the operator image and defaultGarageImage for Garage pods that omit spec.image. For supply-chain policy, use image.digest for the operator and pin spec.image or defaultGarageImage to a digest.
Verify release artifacts¶
Released container images and Helm charts are signed with keyless cosign
signing by GitHub Actions and carry provenance attestations. Release images
also carry an SPDX SBOM. Verify the immutable image digest before placing it in
image.digest or a GarageCluster.spec.image:
IMAGE=ghcr.io/rajsinghtech/garage-operator:v0.8.2
cosign verify "$IMAGE" \
--certificate-identity-regexp '^https://github.com/rajsinghtech/garage-operator/\.github/workflows/docker\.yml@refs/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify "oci://$IMAGE" --repo rajsinghtech/garage-operator
cosign download attestation "$IMAGE" \
--predicate-type https://spdx.dev/Document/v2.3
For the Helm chart, first resolve its OCI digest, then verify that digest with the Helm publishing workflow identity:
CHART=oci://ghcr.io/rajsinghtech/charts/garage-operator
helm show chart "$CHART" --version 0.8.2
# Resolve the OCI manifest descriptor with an OCI client such as ORAS.
oras manifest fetch --descriptor "$CHART:0.8.2"
# Set CHART_DIGEST to the sha256 digest in that descriptor.
CHART_DIGEST=ghcr.io/rajsinghtech/charts/garage-operator@sha256:<digest>
cosign verify "$CHART_DIGEST" \
--certificate-identity-regexp '^https://github.com/rajsinghtech/garage-operator/\.github/workflows/helm\.yml@refs/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify "oci://$CHART_DIGEST" --repo rajsinghtech/garage-operator
The install.yaml asset attached to a GitHub release has a provenance
attestation as well. Download it and verify it against the repository:
gh release download v0.8.2 --repo rajsinghtech/garage-operator \
--pattern install.yaml
gh attestation verify install.yaml --repo rajsinghtech/garage-operator
Substitute the release being installed for v0.8.2. Pin verified image and
chart digests in production; tags alone are mutable references.
Uninstall¶
CRDs and their custom resources are retained by default. Deleting a CRD deletes its custom resources, so inspect and back up them before removing CRDs:
kubectl get garageclusters,garagenodes,garagebuckets,garagekeys,garageadmintokens,garagereferencegrants -A -o yaml > garage-operator-resources.yaml
The operator does not automatically delete Garage data when its Helm release is removed. Follow the resource-specific deletion and drain procedure before removing storage.