# helm cm-push pushes chart directories straight to ChartMuseum

> helm-push is a Helm plugin that uploads a chart directory or a packaged .tgz to a ChartMuseum server, handling packaging, force pushes, proxied context paths and token authentication on the way. The interesting parts are the environment variable precedence for auth and the cm:// protocol, and the plugin is small enough to read.

**chartmuseum/helm-push** —  Helm plugin to push chart package to ChartMuseum

- Repository: https://github.com/chartmuseum/helm-push
- Stars: 725 · Forks: 172
- Language: Go
- License: Apache-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/chartmuseum-helm-push

## A Helm plugin whose binary comes from the release page

helm-push is a Helm plugin to push chart packages to ChartMuseum, and the installation model is the one Helm defines for plugins. The README says that, based on the version in plugin.yaml, the release binary will be downloaded from GitHub.

```bash
$ helm plugin install https://github.com/chartmuseum/helm-push
```

The plugin.yaml file in the repository root is what makes this work. It names the plugin, declares the command it provides, and pins the version, so Helm can resolve the right release artefact and unpack the right binary. The expected output shows the download and the installation under the name cm-push.

```bash
$ helm plugin install https://github.com/chartmuseum/helm-push
Downloading and installing helm-push v0.11.0 ...
https://github.com/chartmuseum/helm-push/releases/download/v0.11.0/helm-push_0.11.0_darwin_amd64.tar.gz
Installed plugin: cm-push
```

The plugin is written in Go and uses cobra for the command line, and the dependency list is interesting for a Helm plugin because it pulls in both helm.sh/helm/v3 v3.18.5 and helm.sh/helm/v4 v4.1.0. Supporting both major Helm lines is what lets one binary work with an older helm 3 client and a newer helm 4 one, and it is a reasonable thing for a chart publishing tool to have to carry.

The module path is github.com/chartmuseum/helm-push and it requires Go 1.25.0 to build from source.

## Adding the repo, then pushing a directory

The plugin pushes to a repository you have already added to Helm, so the first step is the standard repo add.

```bash
$ helm repo add chartmuseum http://localhost:8080
```

The full list of options for the plugin is available through its own help output.

```bash
$ helm cm-push --help
```

The main workflow is pointing the plugin at a directory that contains a valid Chart.yaml, and the plugin takes care of packaging and uploading.

```bash
$ helm cm-push mychart/ chartmuseum
Pushing mychart-0.3.2.tgz to chartmuseum...
Done.
```

The version in the output comes from the chart itself, and the README shows where that comes from.

```bash
$ cat mychart/Chart.yaml
name: mychart
version: 0.3.2
```

Two things are worth noting about the interface. The repository is the last positional argument, and the chart path is the first, which is the reverse of what a Helm subcommand like helm install would look like. And the plugin does the packaging step itself, so a chart directory and a prebuilt package are handled by the same command.

A custom version can be supplied, which is the behaviour a release script wants when the version lives somewhere other than Chart.yaml.

```bash
$ helm cm-push mychart/ --version="1.2.3" chartmuseum
Pushing mychart-1.2.3.tgz to chartmuseum...
Done.
```

## Overwrite is decided by the server, not the client

The overwrite behaviour is where the plugin has to defer to ChartMuseum's configuration, and the README is precise about the combination of settings.

If the ChartMuseum install is configured with ALLOW_OVERWRITE=true, chart versions are automatically overwritten upon re-upload. Otherwise, unless the install is configured with DISABLE_FORCE_OVERWRITE=true, which applies to ChartMuseum versions above v0.7.1, the --force option can be used to force an upload.

```bash
$ helm cm-push --force mychart-0.3.2.tgz chartmuseum
Pushing mychart-0.3.2.tgz to chartmuseum...
Done.
```

So there are three settings in play. ALLOW_OVERWRITE on the server makes every push overwrite. DISABLE_FORCE_OVERWRITE on the server, available from ChartMuseum above v0.7.1, removes the client's ability to force at all. With neither set, the client can still ask to force, and the server honours it.

The README also calls out the case of a version string you intend to push regularly, such as a development version like 9.9.9-dev1, which requires the ChartMuseum server to be run with ALLOW_OVERWRITE=true. That is a useful warning, because a pipeline that publishes the same version twice fails in a way that looks like a network problem rather than a policy decision.

Pushing an already packaged chart works too, and the README notes this workflow does not require the use of helm package.

```bash
$ helm cm-push mychart-0.3.2.tgz chartmuseum
Pushing mychart-0.3.2.tgz to chartmuseum...
Done.
```

## The cm:// protocol exists so tokens reach downloads too

The plugin defines a cm:// protocol that can be used when adding a repository, and the reason is a specific gap in how Helm handles authentication.

```bash
$ helm repo add chartmuseum cm://my.chart.repo.com
```

The only real difference from using http or https is that the environment variables the plugin recognises are then used to set the Authorization header appropriately. As the README puts it, if you do not add the repo in this way, you are unable to use token-based auth for GET requests, which covers downloading index.yaml and chart .tgz files.

That is the practical reason to use it. With a plain https repository, Helm's own client handles the GET side with the credentials stored for that repo, and the plugin has to find its own way to authenticate the upload. With cm://, the plugin is in the path for both directions and can apply the same token to both.

By default cm:// translates to https://. If the server is only reachable over plain http, there is an environment variable for that.

```bash
$ export HELM_REPO_USE_HTTP="true"
```

The plugin also accepts a URL as the second argument directly, in which case the repository does not have to be added beforehand.

```bash
$ helm cm-push mychart-0.3.2.tgz http://localhost:8080
Pushing mychart-0.3.2.tgz to http://localhost:8080...
Done.
```

## Auth precedence runs from repository credentials to bearer token

The authentication section layers four mechanisms, and the order matters when more than one is present.

Basic auth is the default path. If the repository was added with the --username and --password flags, or with the credentials embedded in the URL, no further setup is required, because the plugin reads the auth info located in ~/.config/helm/repositories.yaml. A server running with AUTH_ANONYMOUS_GET=true can allow anonymous downloads while still requiring credentials for pushes, and in that case the plugin recognises two environment variables for basic auth on push operations.

```bash
$ export HELM_REPO_USERNAME="myuser"
$ export HELM_REPO_PASSWORD="mypass"
```

Token auth comes next, and the state of it is honest: ChartMuseum token-auth is currently in progress, and the repository does not define or accept a token format yet. What is supported is the case where ChartMuseum sits behind a proxy that accepts access tokens.

```bash
$ export HELM_REPO_ACCESS_TOKEN="<token>"
```

Setting it causes all of the basic auth options to be ignored, and the plugin sends the token in the Authorization header as a bearer token. If a custom header name is required, a second variable replaces that header entirely.

```bash
$ export HELM_REPO_AUTH_HEADER="<myheader>"
```

A fourth source is a config file. For users of Managed Helm Repositories from Codefresh, the plugin can auto-detect an API key from ~/.cfconfig, managed by the Codefresh CLI, and that key is used for token-based auth, overriding the basic auth options described above. The file format is a contexts block with a name and a token per context, plus a current-context entry.

Client certificate options are also exposed, with --ca-file, --cert-file, --key-file and --insecure, each with a matching HELM_REPO_ environment variable. The README notes that ChartMuseum itself has no options to set up TLS client cert authentication yet, so these are for a frontend that does.

## A proxy prefix needs the context path on both sides

When ChartMuseum runs behind a proxy that adds a route prefix, the plugin has to build the upload URL differently from the URL Helm uses for downloads. The README gives the mapping as a concrete example, with a public URL rewriting to the service address.

```bash
helm repo add chartmuseum https://my.chart.repo.com/helm/v1
helm cm-push --context-path=/helm/v1 mychart-0.3.2.tgz chartmuseum
```

The --context-path option does the job, and the HELM_REPO_CONTEXT_PATH environment variable is the equivalent for scripts.

There is a second, less obvious route. The plugin can read serverInfo.contextPath from the index.yaml of the repository, and the shape of that file is shown in the README.

```yaml
apiVersion: v1
entries:{}
generated: "2018-08-09T11:08:21-05:00"
serverInfo:
  contextPath: /helm/v1
```

The entries field is empty in the example because the snippet is showing the structure rather than a real index, but the point is the serverInfo block. And the README notes that on a ChartMuseum server above version 0.7.1, this contextPath is added to index.yaml automatically if the --context-path option was provided, so the two routes converge once the server is new enough.

This is the section where most broken setups end up. A mismatched context path produces a 404 on upload while helm repo update and helm install keep working, because the read path and the write path are constructed differently.

## Small project, permissive licence, uneven release cadence

The repository layout matches a focused tool: cmd/, pkg/, scripts/, testdata/, acceptance_tests/, a plugin.yaml, a .goreleaser.yml, a Makefile and a CHANGELOG.md, with BUILDING.md alongside. The Makefile shows six build targets, for Linux, macOS and Windows on both amd64 and arm64, and the .goreleaser.yml is what produces the release archives that the plugin installer downloads.

The licence is Apache-2.0, which is a permissive choice with an explicit patent grant and no copyleft obligation for a build that links the plugin into a publishing pipeline. The repository also carries a LICENSE file and a CHANGELOG.md for release history.

The release cadence is uneven in a way worth knowing about. Version 0.10.4 was published on 2023-06-05, and then there was a long gap before v0.11.0 and v0.11.1, both on 2026-02-09, a day apart. The last push was on 2026-04-09 and the repository is not archived, so work is still happening, but there is no recent release to point at.

That gap between the last release and the last commit is the number to keep in mind for a plugin. Because the binary is downloaded by version from the release page, a developer on v0.11.1 and a CI runner that installs from the same source are in step, but neither sees the commits that landed after February. The dependency set tells you what the fix list looked like at that point, with Helm v3.18.5 and v4.1.0 both supported and the build requiring Go 1.25.0.

## Conclusion

Use helm cm-push if you already run ChartMuseum and want a single command that packages and uploads a chart directory without a separate helm package step, especially behind a prefixing proxy where the context path has to be set. Skip it if your charts are published through CI to a plain object store, since the plugin is specific to ChartMuseum. Before wiring it into a pipeline, check whether the server allows overwrites, because a repeated version needs ALLOW_OVERWRITE on the server or the --force flag, and confirm that your proxy is not stripping the Authorization header on the upload request.

## FAQ

### How do I install the helm cm-push plugin?

Run helm plugin install https://github.com/chartmuseum/helm-push. Based on the version in plugin.yaml, the release binary is downloaded from GitHub, and the plugin is installed under the name cm-push.

### How do I push a chart directory to ChartMuseum?

Add the repository with helm repo add, then run helm cm-push with the chart directory and the repository name, for example helm cm-push mychart/ chartmuseum. The plugin packages the chart and uploads it.

### How do I overwrite an existing chart version?

If the server runs with ALLOW_OVERWRITE=true, versions are overwritten automatically on re-upload. Otherwise, unless the server sets DISABLE_FORCE_OVERWRITE=true, you can use the --force option. Pushing the same version regularly, such as a 9.9.9-dev1 version, requires ALLOW_OVERWRITE=true on the server.

### What is the cm:// protocol in helm-push?

It is a custom protocol you can use when adding a repository, as in helm repo add chartmuseum cm://my.chart.repo.com. The difference is that the plugin recognises its environment variables and uses them to set the Authorization header, which is what allows token-based auth to work for GET requests such as index.yaml and chart downloads.

### How does helm-push authenticate when ChartMuseum is behind a proxy?

The plugin can send a token in the Authorization header using HELM_REPO_ACCESS_TOKEN, which overrides the basic auth options, and HELM_REPO_AUTH_HEADER replaces that header name with a custom one. It also reads an API key from ~/.cfconfig for Codefresh managed repositories, and exposes --ca-file, --cert-file, --key-file and --insecure for TLS client certificates.

### How do I push to a ChartMuseum behind a proxy with a path prefix?

Use the --context-path option or the HELM_REPO_CONTEXT_PATH environment variable so the plugin builds the upload URL correctly, for example helm cm-push --context-path=/helm/v1 mychart-0.3.2.tgz chartmuseum. The path can also be supplied in the repository index.yaml as serverInfo.contextPath.

## Sources

- [chartmuseum/helm-push on GitHub](https://github.com/chartmuseum/helm-push)
- [Issues](https://github.com/chartmuseum/helm-push/issues)
- [License: Apache-2.0](https://github.com/chartmuseum/helm-push/blob/main/LICENSE)
- [README](https://github.com/chartmuseum/helm-push/blob/main/README.md)
- [Releases](https://github.com/chartmuseum/helm-push/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chartmuseum-helm-push
