Helm Charts (OCI)
Helm 3 stores charts as OCI artifacts, and a CloudRepo Docker repository is an OCI registry. So your charts live in the same repository as your images, reached with the same credential, and there is nothing extra to enable.
There is no separate “Helm repository” type in CloudRepo, and you do not need
helm repo add or an index.yaml. You push to and pull from a Docker
repository over oci://.
Hosted at CloudRepo — see private Docker registry hosting for plans and pricing.
Prerequisites
A Docker repository (see Docker Repositories)
A Generic repository token (
crp_v1_*) from Repository Tokens in the admin portal — the same token class the Docker CLI usesHelm 3.8 or newer (OCI support is on by default from 3.8; on older 3.x releases export
HELM_EXPERIMENTAL_OCI=1)
Log in
helm registry login takes the host alone, exactly like docker login.
No repository path here:
helm registry login [your-organization-name].mycloudrepo.io \
--username [your-minting-account-email] \
--password-stdin <<< "$CLOUDREPO_TOKEN"
The username is the email of the account that minted the token, and the password
is the repository token. An organization owner’s portal password is not accepted
here, for the same reason it is not accepted at docker login — see
Docker Repositories.
Helm writes the credential to its own registry config, not to
~/.docker/config.json.
Package and push a chart
Package the chart, then push it to the repository, not to the chart:
helm package ./my-chart
# -> my-chart-0.1.0.tgz
helm push my-chart-0.1.0.tgz \
oci://[your-organization-name].mycloudrepo.io/repositories/[your-repository-name]
Helm reports the full reference it created:
Pushed: [your-organization-name].mycloudrepo.io/repositories/[your-repository-name]/my-chart:0.1.0
Digest: sha256:...
Important
The push URL ends at the repository — Helm appends the chart name itself.
The chart name comes from Chart.yaml and the tag from the chart version, so
a URL ending in /my-chart would produce .../my-chart/my-chart:0.1.0.
This is the opposite of docker push, where you name the full image
reference yourself.
Important
The literal repositories/ segment is required, just as it is for images. A
reference without it fails at the first request:
Error: failed to perform "Exists" on destination: HEAD
".../v2/[your-repository-name]/my-chart/manifests/sha256:...":
response status code 400: Bad Request
A 400 Bad Request from a helm push is almost always this: check the
reference carries /repositories/ before the repository name.
Pull and install a chart
helm pull addresses the chart, and the version is a flag rather than a tag:
helm pull oci://[your-organization-name].mycloudrepo.io/repositories/[your-repository-name]/my-chart \
--version 0.1.0
That writes my-chart-0.1.0.tgz into the current directory. To install straight
from the registry:
helm install my-release \
oci://[your-organization-name].mycloudrepo.io/repositories/[your-repository-name]/my-chart \
--version 0.1.0
If the repository is marked public, helm pull and helm install work with no
helm registry login at all.
Important
Which commands take the repository, and which take the chart. Helm is not consistent here, and getting it backwards produces a confusing “not found”:
helm pushand aChart.yamlrepository:end at the repository — Helm appends the chart name itself.helm pullandhelm installtake the full chart path.
A repository: with the chart name appended makes Helm ask for
.../my-chart/my-chart and fail with not found.
Chart dependencies
Reference a CloudRepo-hosted chart from another chart’s Chart.yaml with the
oci:// repository URL — again ending at the repository, because Helm appends
the dependency’s name:
dependencies:
- name: my-chart
version: "0.1.0"
repository: "oci://[your-organization-name].mycloudrepo.io/repositories/[your-repository-name]"
Then helm dependency update resolves it using the credential from
helm registry login.
CI/CD
Non-interactive login takes the token on standard input, keeping it out of process listings and shell history:
echo "$CLOUDREPO_TOKEN" | helm registry login [your-organization-name].mycloudrepo.io \
--username "$CLOUDREPO_EMAIL" \
--password-stdin
helm package ./my-chart
helm push my-chart-*.tgz \
oci://[your-organization-name].mycloudrepo.io/repositories/[your-repository-name]
Store the repository token as a CI secret. It is the same token class your Docker builds use, so one secret can serve both.
Troubleshooting
``helm push`` returns 400 Bad Request
The reference is missing the
repositories/segment — see aboveOr the URL includes the chart name; the push URL ends at the repository
``helm push`` returns 401 after a successful ``helm registry login``
Verify the username is the email of the account that minted the token
Verify you used a Generic (
crp_v1_) token; the npm format (crn_v1_) is not accepted hereVerify the token is scoped to the repository you are pushing to
``helm pull`` cannot find a chart you just pushed
Check the chart name and version:
helm pushreported the exact reference it created, and the tag is the chart version, not a name you choosehelm pulltakes--version; a chart reference with:0.1.0appended is not the form Helm expects
Next Steps
Docker Repositories — the Docker CLI setup this page shares credentials with
Docker (OCI) — Docker (OCI) overview