OCI registries are the future of Helm chart distribution, letting you use the same tools and workflows you already use for container images.
Here’s a Helm chart, my-app, version 1.0.0, stored in an OCI registry at ghcr.io/my-org/charts:
# Chart.yaml
apiVersion: v2
name: my-app
version: 1.0.0
description: A simple web application
type: application
# values.yaml
replicaCount: 1
image:
repository: nginx
tag: latest
To push this chart, you first package it:
helm package ./my-app
This creates my-app-1.0.0.tgz. Then, you log in to your OCI registry:
helm registry login ghcr.io
# Enter username and token/password when prompted
Finally, you push the chart:
helm push my-app-1.0.0.tgz oci://ghcr.io/my-org/charts
This command uploads the .tgz file to the specified OCI repository. Helm treats the chart artifact as an OCI image, tagging it with the chart version.
To pull this chart, you use helm pull with the OCI syntax:
helm pull oci://ghcr.io/my-org/charts/my-app --version 1.0.0
This downloads the chart into a directory named my-app in your current working directory. You can then inspect its contents or install it using helm install my-app ./my-app.
The core problem OCI registries solve for Helm is the lack of a standardized, widely adopted repository format. Historically, Helm relied on custom chart repository servers (like ChartMuseum) or simple HTTP servers serving static files. This fragmented the ecosystem and made it difficult to manage chart sources, especially in organizations already invested in container image registries. OCI (Open Container Initiative) registries, like Docker Hub, Harbor, or GitHub Container Registry, provide a universal standard for storing and retrieving container images and, now, Helm charts. By leveraging OCI, Helm gains immediate compatibility with existing infrastructure, authentication mechanisms (like docker login), and tooling. This means you can use helm registry login which often just uses your existing container registry credentials. The helm push and helm pull commands now understand the oci:// prefix, abstracting away the underlying registry interactions. Helm charts are essentially stored as OCI image layers, with the chart metadata and files bundled into a manifest. This allows for efficient storage and retrieval, and enables features like image signing and vulnerability scanning directly on your Helm charts.
You can also reference charts directly in your requirements.yaml or Chart.yaml when using Helm dependencies:
# requirements.yaml
dependencies:
- name: my-app
version: "1.0.0"
repository: "oci://ghcr.io/my-org/charts"
Running helm dependency update will then fetch my-app from the OCI registry. This makes managing dependencies across different Helm repositories seamless, as you can mix and match OCI and traditional Helm repositories.
When you push a chart to an OCI registry, Helm doesn’t just upload a single blob. It converts the chart archive into an OCI image. The Chart.yaml and values.yaml become part of the image’s configuration, and the rest of the chart’s files are stored as image layers. The image tag is derived from the chart’s version, with potential suffixes for stability (e.g., 1.0.0-alpha.1). This means that helm pull oci://.../my-app --version 1.0.0 is conceptually similar to docker pull .../my-app:1.0.0, although Helm adds its own interpretation layer. The helm registry login command, when used with a compatible registry, typically leverages the same credentials you would use for docker login or podman login, simplifying authentication significantly. This unified approach to artifact management is a major advantage, allowing teams to manage both application images and their deployment configurations using a single set of tools and security policies.
If you’re using a private OCI registry, you’ll need to ensure your Kubernetes cluster’s imagePullSecrets are configured correctly if you intend to deploy charts directly from the OCI registry using tools like Argo CD or Flux CD, as these controllers will also need to authenticate.