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.

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.
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:
index.yaml; the client picks a version by pulling the index then downloading the .tgz.The advantages that make OCI attractive:
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.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.
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:
helm registry login ghcr.io --username arman \
--password-stdinThen 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/chartsNotice 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:
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.
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.
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 --verifyTwo things different from HTTP repositories to remember:
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.$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.
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.
| Registry | Strengths | Usage notes |
|---|---|---|
| GHCR (GitHub Container Registry) | GitHub-integrated, free for public, per-package visibility | oci://ghcr.io/<org>/<repo>; fits well with GitHub Actions |
| Docker Hub | Familiar, popular, lots of tooling | Log in via token (PAT), not account password |
| GitLab Container Registry | GitLab CI-integrated, per-project | oci://registry.gitlab.com/<group>/<project> |
| AWS ECR | Cheap private registry, IAM policies | Auth via aws ecr get-login-password |
| GCP Artifact Registry | Multi-format (including charts), IAM | oci://<region>-docker.pkg.dev/<project>/<repo> |
| Azure ACR | Azure AD integration, geo-replication | oci://<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:
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/chartsOCI 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
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.
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:
HelmRepository type oci), and internal tooling.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.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.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.
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 login → helm push → helm pull → helm 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:
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.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!