on
Packaging Helm charts as OCI artifacts (hands‑on guide for modern Helm)
Helm’s distribution model has shifted: modern Helm workflows favor OCI registries, artifact signing, and tighter GitOps integration. This hands‑on guide walks through packaging a chart, publishing it as an OCI artifact, signing it with Sigstore/Cosign, and verifying it during deployment — using the current Helm tooling and GitOps-friendly practices.
Why this matters
- Helm 4 marked a major update to the project and accelerated adoption of modern packaging and distribution patterns. The project maintainers explicitly moved toward cleaner APIs and better integration with registries and platform tooling. (cncf.io)
- Many registries and platform vendors are moving away from legacy ChartMuseum-style index.yaml repositories in favor of OCI artifacts, which makes storing charts alongside container images simpler and more secure. Azure and other vendors have pushed users toward OCI-based chart storage. (github.com)
What you’ll need
- Helm (modern release; Helm 3.8+ has stable OCI commands and Helm 4 continues this path) and kubectl. (helm.sh)
- Access to an OCI-compliant registry (GHCR, Docker Hub, Quay, Harbor, ACR, ECR, GCP Artifact Registry, etc.).
- Cosign (from Sigstore) for signing and verifying artifacts, and optional GitOps operator (Flux or Argo CD) if you want automated verification in your pipeline. (github.com)
Quick summary of the flow
- Package your chart (helm package or helm chart save).
- Authenticate to your OCI registry (helm registry login).
- Save and push the chart as an OCI artifact (helm chart save / helm chart push or helm push depending on client version).
- Sign the pushed artifact with cosign.
- Deploy (helm install/upgrade or via GitOps operator) and verify the signature during CI or at reconcile time.
Step-by-step
1) Prepare and package the chart
- From your chart directory:
helm lint ./mychart helm package ./mychart # produces: mychart-0.1.0.tgzHelm’s packaging still produces a .tgz artifact, but that archive can now be uploaded to an OCI registry rather than an index.yaml-based repo. (helm.sh)
2) Log in to your OCI registry
- Use Helm’s registry login to authenticate (this uses the same credentials patterns as Docker/OCI registries):
helm registry login ghcr.io # or for generic: helm registry login registry.example.comIf you prefer, use docker/podman login first — many registries allow the same credentials for Helm. (v3-1-0.helm.sh)
3) Save and push the chart as an OCI artifact
- Two common command patterns depending on Helm version and preference:
- Save + push (explicit chart commands):
helm chart save ./mychart oci://registry.example.com/myrepo/mychart:0.1.0 helm chart push oci://registry.example.com/myrepo/mychart:0.1.0 - Or package then push:
helm package ./mychart helm push mychart-0.1.0.tgz oci://registry.example.com/myrepoHelm maps the chart name and semver into an OCI tag; that helps you manage versions consistently in the registry. Consult your registry docs — some registries provide a web UI to inspect pushed charts. (helm.sh)
- Save + push (explicit chart commands):
4) Sign the chart with Cosign (provenance and integrity) Signing gains importance when charts travel through CI/CD and multiple teams. Sigstore’s cosign can sign OCI artifacts; the signature is stored alongside the artifact in the registry (as a referrer), enabling verification down the line.
Example (keyless signing with OIDC — common for CI pipelines):
# install cosign first, then:
cosign sign --key <key-or-use-keyless> oci://registry.example.com/myrepo/mychart:0.1.0
- For keyless signing you’ll typically configure your CI provider’s OIDC provider (GitHub Actions, GitLab CI, etc.) and then run cosign without storing long-lived private keys.
- Alternatively, use the helm-sigstore plugin that integrates sigstore verification into Helm workflows. (github.com)
5) Verify signatures before deploy (CI or GitOps)
- Locally, you can verify a chart:
cosign verify oci://registry.example.com/myrepo/mychart:0.1.0 # or with helm plugin helm sigstore verify mychart-0.1.0.tgz - In GitOps flows (Flux has explicit examples), enable policy that requires signed artifacts and configure the operator to verify signatures during reconciliation. That makes the cluster reject unsigned or tampered artifacts automatically. (fluxcd.control-plane.io)
Deploying the OCI chart
- To install directly with Helm:
helm install myapp oci://registry.example.com/myrepo/mychart --version 0.1.0 - For GitOps (Flux example) you reference the OCI chart and optionally enable verification fields in the HelmRelease so Flux will verify the cosign signature during reconciliation. This keeps attestation in the deployment loop rather than only in CI. (fluxcd.control-plane.io)
Troubleshooting and gotchas
- Tags and SemVer: Helm expects chart name and semver mapping to tags; avoid using :latest. If your version contains + characters, Helm may translate them (older quirks exist). Always use explicit versions when publishing. (devopsie.com)
- Registry quirks: Some registries handle referrers/signatures differently or require specific features to display signatures (Harbor and others have had integration issues). If signatures don’t show in the UI but cosign verifies the artifact, check registry-specific docs and cosign/referrers mode compatibility. (kisonik.una.io)
- Legacy index.yaml repositories: Some teams still rely on index-based chart repos. Moving to OCI means changing scripts and CI pipeline steps that previously updated index.yaml. Plan the migration and ensure your deployment tooling (and dependent teams) understand the new flow. Vendor guidance and support pages often document migration paths. (github.com)
Best practices checklist
- Version everything: publish charts with explicit semantic versions and avoid mutable tags in production.
- Sign in CI: run cosign signing in your CI pipeline using OIDC (keyless) where possible so you don’t manage long-lived private keys.
- Enforce verification in GitOps: shift signature verification to the reconciliation agent (Flux/Argo CD) so the cluster only accepts signed charts. (fluxcd.control-plane.io)
- Keep values separate and auditable: store environment-specific values in the GitOps repo (or sealed secrets manager) rather than embedding secrets inside charts.
- Test the pull path: delete local copies and run a full pull->verify->install from the registry to confirm the production path works as expected.
Why this is a timely topic
- The Helm project’s evolution and the broader cloud-native ecosystem’s move toward OCI artifact models and signed provenance makes this workflow a core operational requirement for teams packaging Kubernetes applications. Vendors and registries increasingly expect charts to be OCI artifacts rather than legacy index repos, so packaging charts as OCI artifacts and integrating signing/verification is now practical and recommended. (cncf.io)
Closing notes Adopting OCI-based Helm distribution plus Sigstore signing turns charts into first-class, verifiable artifacts you can reliably store and serve from the same registries you use for images. That simplifies supply-chain controls, accelerates GitOps flows, and aligns Helm packaging with modern security and operational patterns. For immediate reference, check the Helm documentation on registries and the Sigstore/Cosign project for signing examples, and consult your registry provider for provider-specific details. (helm.sh)
References
- CNCF announcement and Helm 4 release notes. (cncf.io)
- Helm project blog: Path to Helm v4. (helm.sh)
- Helm docs: Use OCI-based registries / Registries topic. (helm.sh)
- Azure ACR deprecation and migration guidance toward OCI chart storage. (github.com)
- Cosign and Sigstore Helm tooling + GitOps verification examples. (devopsie.com)