How does Helm authenticate to a private OCI registry, and where does it keep those credentials?
answer
- Authentication attaches to a host, not a chart
- Helm has its own credential file
- An environment variable names that path
- Same file shape another client already writes
- Logging out is purely local
basics
~20 sRun helm registry login against the registry host, optionally reading the password from standard input. Helm writes the credential into its own registry config file, named by HELM_REGISTRY_CONFIG, and every later oci:// operation against that host uses it. helm registry logout removes the entry.
solid answer
~40 sAuthentication is per registry **host**, not per chart: `helm registry login registry.example.internal -u ci-bot --password-stdin` stores a credential that every subsequent `helm install`, `helm pull`, `helm push` or dependency resolution against `oci://registry.example.internal/...` reuses. Helm keeps it in its own file — the path is in `HELM_REGISTRY_CONFIG`, by default `registry/config.json` under the Helm config directory, and `helm env` prints it. The file uses the same JSON shape a container client uses, which is why a CI job can point `HELM_REGISTRY_CONFIG` at a config the image-pull step already wrote instead of logging in twice. `helm registry logout registry.example.internal` deletes the local entry; it does not revoke anything server-side. `helm repo add --username/--password` is for classic HTTP repositories and has no effect on `oci://` references. Public paths need no login at all.
code
bash · 3 linesprintf '%s' "$REGISTRY_TOKEN" | helm registry login registry.example.internal -u ci-bot --password-stdin
helm pull oci://registry.example.internal/platform-charts/tileserver --version 2.7.14
helm registry logout registry.example.internalgo deeper
Know the command shape: helm registry login against the host, then ordinary oci:// commands just work. Remember that logging in is per registry, not per chart.
Explain where the credential is stored, which environment variable names that file, and why a login performed by other tooling does not automatically apply to Helm.
Show how you keep tokens short-lived and path-scoped in CI, why --password-stdin matters, and what you actually do when a publishing credential leaks.
Own the identity model: which jobs may push to which registry paths, how those grants are reviewed, and whether chart and image publishing should share one credential at all.
## The command ```bash helm registry login registry.example.internal --username ci-bot --password-stdin < token.txt ``` The argument is a **registry host**, not a chart and not a path. Once that succeeds, everything Helm does against `oci://registry.example.internal/...` is authenticated: `helm install`, `helm upgrade`, `helm pull`, `helm show`, `helm push`, and dependency resolution for a `Chart.yaml` entry whose `repository` points at that host. There is no per-chart credential and nothing to attach to an individual reference. `helm registry logout registry.example.internal` is the inverse. It removes the stored entry from the local file. It is a local operation only — it does not invalidate a token, revoke a session, or tell the registry anything. If a credential leaked, logging out is not the remedy; rotating it at the registry is. For an anonymous, publicly readable path, no login is needed at all. Helm will try unauthenticated first, and only a registry that demands a credential produces an authorization failure. ## Where the credential lands Helm does **not** use `helm repo add`'s credential handling for registries. Repository credentials given to `helm repo add` belong to the classic HTTP repository path — an `index.yaml` server — and have no bearing on an `oci://` reference. Instead Helm keeps a registry credential file of its own: ```bash helm env | grep HELM_REGISTRY_CONFIG # HELM_REGISTRY_CONFIG="/home/ci/.config/helm/registry/config.json" ``` `HELM_REGISTRY_CONFIG` names the file; the default lives under the Helm configuration directory. The file's JSON shape is the same one container clients use for their own registry logins, which has a practical consequence worth knowing: **Pointing `HELM_REGISTRY_CONFIG` at an existing container-client config makes Helm reuse that login.** In a CI job that has already authenticated to pull or push images, exporting `HELM_REGISTRY_CONFIG=$DOCKER_CONFIG/config.json` (or wherever the job wrote it) saves a second login step and a second copy of the secret in the job environment. The converse is the failure people actually hit: a pipeline runs an image-registry login, then `helm pull oci://...` fails with an authorization error, and the engineer concludes Helm is broken. It is not — Helm read *its own* config path, which nobody wrote to. Either run `helm registry login` in the same job, or point `HELM_REGISTRY_CONFIG` at the config that the other login produced. ## Operating it in CI A few habits separate a working pipeline from a fragile one: - **Use `--password-stdin`.** Passing a token as `--password` puts it in the process table and, on many CI systems, into a command echo in the log. - **Prefer a short-lived token** issued to the job over a long-lived robot password. Registries that can mint job-scoped tokens make the credential worthless minutes after the job ends. - **Log in once per job, not per command.** The credential file persists for the life of the workspace, so one login covers the whole job — the `helm dependency` resolution, the `helm push`, and any `helm upgrade`. - **Scope by path.** Access control lives in the registry, and it is normally expressible per repository path, so a chart-publishing job's credential can be limited to `platform-charts/*` rather than the whole registry. - **Never put registry credentials in a values file.** Values end up stored with the release and printed by ordinary inspection commands; a registry credential does not belong there. ## Private CAs and plain HTTP A registry behind a private certificate authority, or one served without TLS in a lab, needs to be told so. Both `helm registry login` and the chart-fetching commands accept options for supplying a CA certificate and a client certificate/key pair, and for talking to a registry that is not using TLS. Check `helm registry login --help` on the version you run rather than guessing the spelling, because these are the flags that most often differ between environments; the behaviour, not the spelling, is what an interview is testing. ## What does not change with Helm 4 The registry credential model is one of the pieces Helm 4 left alone: same `helm registry login` and `logout` commands, same `HELM_REGISTRY_CONFIG`, same host-level scope, same relationship to the container-client config format. If you learned it on Helm 3, it still holds.
- A CI job authenticates to the registry for its image build, then helm pull against the same registry fails as unauthorized. Why?Helm reads the credential file named by HELM_REGISTRY_CONFIG, which defaults to a path under the Helm configuration directory — not the file the image tooling wrote. The fix is either to run helm registry login in the same job, or to export HELM_REGISTRY_CONFIG pointing at the config the earlier login produced, since the two use the same JSON shape.
- Does helm registry logout invalidate the token at the registry?No. It is a local operation that removes the host's entry from Helm's credential file. The token remains valid until the registry expires or revokes it. If a credential has leaked, revoke it at the registry and rotate it; logging out only stops this machine from presenting it.
- Can you give different credentials to two paths on the same registry host?Helm's stored credential is keyed by host, so one login is in effect at a time for that host in a given credential file. Where a job genuinely needs two identities, isolate them: separate jobs, or separate HELM_REGISTRY_CONFIG files pointed at by the environment. Finer-grained access is expressed by the registry's own path-scoped permissions on each credential, not by Helm.
saying these in an interview costs you the question
- Says helm repo add --username authenticates an oci:// reference
- Assumes a container-client login always covers Helm
- Thinks helm registry logout revokes the token server-side
- Passes the token with --password instead of stdin
- Puts registry credentials in a values file
- Believes a public chart path still requires a login