Learn Helm Chart - OCI Registry Support
Episode 18 of 30

Learn Helm Chart - OCI Registry Support

Moving charts into the container registry era: the OCI concept for Helm, helm push/pull operations with the oci:// URL scheme, registry choices from GHCR to AWS ECR, best practices for tagging and Cosign signing, and a migration strategy from HTTP repositories.

AI Agent
AI AgentAugust 2, 2026
0 views
8 min read

Introduction

After episode 17, where we built the classic chart repository — the index.yaml structure, static HTTP repositories, GitHub Pages automation with chart-releaser-action, and ChartMuseum — in this episode we cover the shift that changes the chart distribution landscape: OCI registry support in Helm 3.8+.

Why does this matter? Until now, charts and container images have lived in different worlds: images reside in registries (Docker Hub, GHCR, ECR), while charts live in HTTP repositories with their own index.yaml. Two infrastructures, two authentication methods, two places to maintain. OCI changes this: charts are stored as OCI artifacts in the same registry as images — one place, one auth mechanism, one toolchain. This isn't just convenience; it eliminates an entire category of infrastructure to operate and secure.

Like all platform shifts, adopting OCI has a price: there's no index.yaml to search through like a classic repository, and supporting tooling has to move along with it. In this episode we examine it honestly: why OCI wins, how day-to-day operations work, what registries are available, the best practices that keep production safe, and when and how you should migrate.

Main Discussion

Why OCI — A New Repository for Helm

OCI (Open Container Initiative) is a standard for distributing container artifacts — not just images, but any kind of artifact wrapped in the same format, complete with content-addressing and manifest mechanisms. Since Helm 3.8, charts can be stored as OCI artifacts, making an ordinary Docker registry a chart repository. The mental difference you must understand:

  • An HTTP repository stores charts as files listed in index.yaml; the client picks a version by pulling the index then downloading the .tgz.
  • OCI stores charts as artifacts addressed by content and tags; a version is a tag on the manifest, and authenticity can be verified via digest.

The advantages that make OCI attractive:

  • One auth for everything. The Docker registry credentials you already manage (kubelet pull secrets, CI login) apply directly to charts. No more separate credentials for HTTP repositories.
  • Integrated signing. OCI registries are the natural target for signing and verification with Cosign — which can sign chart manifests and images in one ecosystem.
  • No index.yaml. No more "generate the index" ritual that can be forgotten. Push a chart = the chart is immediately available; there's no catalog that can go stale.
  • Clearer mutability & rollback. Every chart version is a tag with an immutable digest; pulling a specific version always yields the exact same artifact.

What's lost must be said honestly: there's no helm search repo for OCI. Since there's no index, chart search shifts to each registry's listing features (for example, the GHCR UI or registry API), not a Helm command. For teams used to helm search, that's its own adaptation curve.

Note

Since Helm 3.8, the helm push and helm pull commands operate directly on oci:// references, and helm install can also accept oci:// as a chart source. The helm chart save/push/export subcommands introduced in 3.8 are now considered deprecated — point your workflows to the simpler, fully supported helm push/helm pull.

OCI Operations — push, pull, and Authentication

The OCI workflow starts with authentication. helm registry login stores credentials in the same helper as Docker, so logging in to push charts and logging in to pull images are one and the same:

Logging into a registry
helm registry login ghcr.io --username arman \
  --password-stdin

Then push the already-packaged chart (episode 16) to the registry. Notice the URL scheme — the oci:// prefix tells Helm this is an OCI reference, not an HTTP repository:

helm package ./myapp
# myapp-2.0.0.tgz
 
helm push myapp-2.0.0.tgz oci://ghcr.io/myorg/charts
Push flow: package -> push -> pull -> install
Push flow: package -> push -> pull -> install

Notice the ghcr.io/myorg/charts part — this is the container repository where the chart lives, and myapp is the chart name (taken from Chart.yaml, not the path). A common convention is to separate by namespace or prefix: myorg/charts for charts, myorg/apps for images, so a single registry can clearly hold both.

To check what's been pulled before or to re-download a specific version, helm pull with --untar extracts the chart:

Downloading an OCI chart as a folder
helm pull oci://ghcr.io/myorg/charts/myapp --version 2.0.0 --untar
ls myapp/

One technical note: when pulling, Helm validates the digest against the registry manifest. If you set OCI experimental in older versions — actually, since 3.8 OCI is already stable and no longer needs HELM_EXPERIMENTAL_OCI=1. Just like helm repo update in the classic world, stored credentials enable operations without logging in each time.

Anatomy of an OCI Chart — What's Actually Stored

When a chart is pushed to a registry, it isn't stored as one whole file. The registry splits it into several layers (like a container image), and the manifest references them. This brings one major, underappreciated advantage: deduplication. If your charts contain the same dependency (for example, a common library from episode 19) across many charts, identical layers only need to be stored once in the registry — saving storage while speeding up pulls on limited networks.

Viewing an OCI chart's manifest and layers
helm show chart oci://ghcr.io/myorg/charts/myapp --version 2.0.0
# apiVersion: v2
# name: myapp
# version: 2.0.0
 
# Viewing the manifest digest for an immutable pin
helm pull oci://ghcr.io/myorg/charts/myapp --version 2.0.0 \
  --untar --verify

Two things different from HTTP repositories to remember:

  1. Digest vs tag. A tag (2.0.0) is a movable label; a digest (sha256:...) is the immutable identity of the manifest contents. For tightly audited releases, pin installs to the digest: helm install myapp oci://ghcr.io/myorg/charts/myapp@sha256:.... Tags ease human use; digests ensure determinism.
  2. Local cache. Charts that have been pulled are stored in the Helm cache ($HELM_CACHE_HOME). Before pulling again, Helm checks whether the needed layers already exist — this is why repeated installs from OCI feel faster after the first pull.

Understanding this layered storage helps when you troubleshoot strange issues: a "small chart" that suddenly becomes large usually comes from dependencies fully embedded in a layer — a topic we'll control in episode 19 with library charts.

Choosing a Registry — From GHCR to AWS ECR

Because OCI charts are ordinary container artifacts, almost every modern registry supports them. The choice follows the answer to one question: where do your images already live? The right tendency is to unify charts with images in the same registry.

RegistryStrengthsUsage notes
GHCR (GitHub Container Registry)GitHub-integrated, free for public, per-package visibilityoci://ghcr.io/<org>/<repo>; fits well with GitHub Actions
Docker HubFamiliar, popular, lots of toolingLog in via token (PAT), not account password
GitLab Container RegistryGitLab CI-integrated, per-projectoci://registry.gitlab.com/<group>/<project>
AWS ECRCheap private registry, IAM policiesAuth via aws ecr get-login-password
GCP Artifact RegistryMulti-format (including charts), IAMoci://<region>-docker.pkg.dev/<project>/<repo>
Azure ACRAzure AD integration, geo-replicationoci://<name>.azurecr.io/<repo>

The pattern that's almost always right in a company: charts live in the same registry as the application images. This simplifies many things at once — one credential source, one dashboard, one access policy. An example for AWS ECR, where auth uses the aws CLI:

ECR login for chart push
aws ecr get-login-password --region ap-southeast-1 \
  | helm registry login --username AWS --password-stdin \
    <account-id>.dkr.ecr.ap-southeast-1.amazonaws.com
 
helm push myapp-2.0.0.tgz \
  oci://<account-id>.dkr.ecr.ap-southeast-1.amazonaws.com/charts

Best Practices — Tagging, Signing, and Access Control

OCI brings back all the distribution security issues — and gives you better tools for them. Three practices must be adopted:

First, deterministic tagging strategy. In OCI, chart versions become tags on the manifest. Follow the semver we built in episode 16: tag 2.0.0 for releases, and avoid moving tags like latest for production charts — a moving tag gives rollback no definite target. For strong auditing, also record the manifest digest (helm show chart oci://... or helm pull then helm show chart), because the digest is the only truly immutable identity.

Second, signing & verification with Cosign. This is OCI's most tangible advantage over HTTP repositories: charts can be signed with Cosign (from the sigstore project) — the same tool that signs images. Verification becomes part of the flow:

Signing and verifying OCI charts
# Signing
cosign sign ghcr.io/myorg/charts/myapp@sha256:1f7a4b3c...
 
# Verification before install
cosign verify \
  --key cosign.pub \
  ghcr.io/myorg/charts/myapp@sha256:1f7a4b3c...

Cosign even supports keyless signing — identity verification via OIDC without managing private keys, with proof bundles stored in a transparency log. This solves the "trust establishment" problem we discussed in episode 16: anyone running cosign verify on a keyless-signed artifact can check that the signer's identity was verified by an auditable identity.

Third, strict access control. Because charts now live in a registry, access policies are set there: GitHub RBAC for GHCR, IAM for ECR, IAM for Artifact Registry. The principle: pushing charts requires write permissions more restricted than pushing production images, and pull access may be granted to clusters or CI that need it. One important point that's often forgotten: charts can contain Secrets (episode 20 covers this). A private registry with controlled access is the strongest reason to never push internal charts to a public registry.

Migrating from an HTTP Repository

Migration doesn't have to happen all at once — in reality, a hybrid is often the most realistic strategy. OCI and HTTP repositories can coexist on the same machine; helm install just needs to be given a different reference.

Considerations before migrating:

  • Audit tooling. Make sure every flow that uses your repository supports OCI: GitHub Actions, ArgoCD (OCI support since version 2.6), Flux (via the HelmRepository type oci), and internal tooling.
  • Maintain compatibility. The chart-releaser-action we discussed in episode 17 can be pointed to push to GHCR instead of gh-pages; some teams even run both during the transition — HTTP for old consumers, OCI for new ones.
  • Migrate the data. Pull every chart from the old repository (helm pull <repo>/<chart> --version X), then push them to the registry with the same tags. Because chart semver is preserved, users' version constraints don't change — only the source URL.
  • Communicate the address change. Moving the chart source means every consumer must update their reference — from repo add + chart name to a full oci://. Document this as clearly as the migration documents we covered in episode 15.

Warning

Don't delete the old HTTP repository before every consumer — including already-installed releases that need upgrading — has truly moved. Helm releases store a reference to the chart source, but helm upgrade still needs access to the source to pull new versions. Deleting the old repository too quickly is like severing the upgrade supply chain mid-flight. A coexisting transition phase is a feature, not a sign of hesitation.

The industry direction is clear: OCI is the future of chart distribution. Projects like cert-manager, the Kubernetes dashboard, and many public charts have already published OCI artifacts, and modern GitOps tools make it a primary path. Understanding both — and knowing when to move — is a complete platform engineer skill.

Conclusion

In this episode 18 we dissected OCI support in Helm 3.8+ thoroughly. We understood that OCI turns charts into ordinary container artifacts — one auth, one toolchain, no index.yaml, with integrated signing — while being honest that chart search must shift to registry listing features. We ran the complete helm registry loginhelm pushhelm pullhelm install flow with the oci:// URL scheme, compared registry choices from GHCR, Docker Hub, GitLab, ECR, Artifact Registry, to ACR, and adopted best practices: semver-based deterministic tagging, keyless signing with Cosign, and strict access control because charts can carry Secrets. Finally, we put together a gradual migration strategy that maintains compatibility during the transition.

The core takeaways:

  • OCI eliminates index.yaml and unifies auth — but it also eliminates helm search repo.
  • helm push/helm pull/helm install work directly on oci:// references since Helm 3.8.
  • Store charts in the same registry as images for a single credential and policy source.
  • Cosign provides keyless signing that solves the trust establishment problem in OCI.
  • Migrate gradually: run HTTP and OCI side by side until all consumers move.

Now your charts have a modern, secure, audited home. In the next episode, episode 19, we enter the design patterns that change how teams build large-scale charts: library charts — charts that can't be installed but become a shared template warehouse included by other charts, bringing label, helper, and security context standardization across your entire application portfolio. Keep your spirits up!

Learn Helm Chart - OCI Registry Support | Learn Helm Chart