ChartMuseum: a self-hosted Helm chart repository with a storage backend you already own
helm chart repository server
At a glance
- What is it?
- ChartMuseum is a Go server that speaks the classic Helm chart repository protocol and adds an upload API on top. It is a good fit when you want charts in object storage you control, and a poor fit if you have already moved to OCI registries.
- Who is it for?
- Adopt ChartMuseum if you need the classic index.yaml repository protocol, an HTTP upload API for CI, and charts stored in a bucket you already pay for. Skip it if your delivery pipeline is already OCI-based, since the README describes no OCI support and a registry gives you that without a second service.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem ChartMuseum solves: Helm needs an index.yaml, and someone has to serve it
A Helm chart repository is not a database. It is a static file layout: an index.yaml at the root, chart tarballs under /charts/, and optional provenance files beside them. Helm clients fetch the index, resolve versions, then download the tarball. That means any web server can host a repository, but a plain web server gives you no way to publish. Someone still has to build the tarball, regenerate the index, and copy both to the right place.
ChartMuseum takes that publishing step and turns it into an HTTP call. The README describes it as an open-source Helm Chart Repository server written in Go, with support for cloud storage backends including Google Cloud Storage, Amazon S3, Microsoft Azure Blob Storage, Alibaba Cloud OSS, Openstack Object Storage, Oracle Cloud Infrastructure Object Storage, Baidu Cloud BOS, Tencent Cloud COS, DigitalOcean Spaces, Minio and etcd. The important part is the second half of that sentence. ChartMuseum does not own your charts. It writes them into a bucket or a directory you already operate, and serves the index from there.
The audience is platform and release engineers who run their own CI and want a chart endpoint with an upload API, without standing up a full registry. If your charts are public and few, a static bucket plus a generated index is less machinery. ChartMuseum earns its place when uploads are frequent, when multiple pipelines push, and when you want the server to keep the index consistent instead of a script doing it.
How the server is put together: Gin routes, a storage interface, and chart parsing from Helm itself
The README lists the Go libraries the project is built on, and that list is effectively the architecture. HTTP routing is gin-gonic/gin. Command line parsing is urfave/cli and configuration is spf13/viper, which is why every flag can also arrive as an environment variable. Logging is uber-go/zap. Chart handling comes from helm/helm itself, so the server parses charts with the same library the client uses. Authentication lives in a separate module, chartmuseum/auth, and storage in chartmuseum/storage. Those two are split out rather than vendored in, which is why the go.mod file shows them as ordinary dependencies at v0.6.0 and v0.17.0.
The storage split is the design decision that matters most. A single interface covers local disk, S3, GCS, Azure, and the rest, so the HTTP layer does not know where bytes land. That is what makes `--storage local` and `--storage amazon` interchangeable from the API's point of view. It also means the index is regenerated from what the backend contains, so a bucket that someone edits by hand can drift from what the server reports.
On the read side the routes are the conventional repository ones. The README states that `GET /index.yaml` is what Helm retrieves when you run `helm repo add chartmuseum http://localhost:8080/`, and that `GET /charts/mychart-0.1.0.tgz` is what a `helm install` pulls. On the write side there is a JSON-ish API: `POST /api/charts` to upload a version, `POST /api/prov` for a provenance file, `DELETE /api/charts/<name>/<version>` to remove one, plus `GET` endpoints to list charts, list versions of a chart, describe a version, and fetch a chart's templates or values. There are also `HEAD` routes to check whether a chart or a version exists, which is the cheap way for CI to avoid re-uploading.
One detail worth noticing: the README's configuration example includes `depth: 2` and a set of bearer-auth keys (`bearerauth`, `authrealm`, `authservice`, `authcertpath`, `authactionssearchpath`). That is the shape of a deployment behind an existing auth service rather than one with its own user database. ChartMuseum does not ship a user model; it delegates.
Installing ChartMuseum and pushing a first chart
The README gives two installation paths. The installer script downloads a release binary:
curl https://raw.githubusercontent.com/helm/chartmuseum/main/scripts/get-chartmuseum | bashAlternatively, the README points at the releases page, which it says also contains all package checksums and signatures. After installing, `chartmuseum --version` prints the version, and `chartmuseum --help` lists every flag.
For a first run, the README's configuration file example is the clearest starting point. It sets a port, a storage backend and a root directory, along with the bearer-auth keys.
debug: true
port: 8080
storage.backend: local
storage.local.rootdir: <storage_path>
bearerauth: 1
authrealm: <authorization server url>
authservice: <authorization server service name>
authcertpath: <path to authorization server public pem file>
authactionssearchpath: <optional: JMESPath to find allowed actions in a jwt token>
depth: 2With the server up at http://localhost:8080, package a chart and upload it. The README's example builds the tarball with the Helm CLI and then posts it as a binary body:
cd mychart/
helm package .
curl --data-binary "@mychart-0.1.0.tgz" http://localhost:8080/api/chartsIf you signed the package and generated a provenance file, the README shows uploading it separately to `/api/prov`, or sending both at once as multipart form data:
curl -F "[email protected]" -F "[email protected]" http://localhost:8080/api/chartsThere is also a plugin path. The README notes that `helm cm-push mychart/ chartmuseum` works via the helm-push plugin. Once the chart is in, add the repository and install from it:
helm repo add chartmuseum http://localhost:8080
helm search repo chartmuseum/
helm install chartmuseum/mychart --generate-nameFor S3 and S3-compatible services the README gives a flag-based example. For Amazon S3 the endpoint is inferred; for Minio and similar services you set credentials in the environment and pass the endpoint.
chartmuseum --debug --port=8080 \
--storage="amazon" \
--storage-amazon-bucket="my-s3-bucket" \
--storage-amazon-prefix="" \
--storage-amazon-region="us-east-1"There is a container image as well. The Dockerfile in the repository builds from alpine, adds cifs-utils and ca-certificates, copies the arch-specific binary to `/chartmuseum`, and runs as user 1000:1000. Note that it expects the binary to already exist at `./_dist/linux-$TARGETARCH/chartmuseum`, so it is a packaging step for the release pipeline, not a source build.
Where ChartMuseum is the wrong tool
The clearest boundary is OCI. The README describes ChartMuseum as a Helm Chart Repository server and lists no OCI registry support. If your organization has standardized on pushing charts as OCI artifacts, ChartMuseum is a second system to run, secure and back up for a protocol you are trying to leave behind. The related search terms people use around this project include comparisons to Harbor and to OCI, and the honest answer from the documentation is that ChartMuseum occupies the older, index.yaml-based side of that split.
The second boundary is authentication. The configuration keys point at an external authorization server: `authrealm`, `authservice`, `authcertpath`, and an optional JMESPath expression for finding allowed actions in a JWT. There is no built-in user store described in the README. A small team that just wants "a password on the chart server" will find themselves either writing that layer or accepting that anyone who can reach the port can push and delete charts. The `DELETE /api/charts/<name>/<version>` route is not read-only.
Third, storage choice has consequences the README does not resolve for you. Local disk is the simplest backend, but a chart repository on local disk is tied to one process on one machine. Moving to S3 or another object store solves that, and it also makes every index lookup depend on the object store's availability and on credentials that must be present in the process environment. The README does not document migration between backends, so switching later means re-uploading charts or copying objects and trusting that the index regenerates correctly.
Finally, there is the deletion problem. ChartMuseum will delete a chart version, but Helm clients cache the index. A deleted version can still be resolvable from a client that has not refreshed. That is a property of the repository protocol rather than a bug in this server, and it is the reason some teams never delete and instead publish a new version.
ChartMuseum against a static bucket, and against Harbor
The most direct alternative is no server at all: a bucket or a static web host with a hand-generated index.yaml. The difference is where the work happens. With a static bucket, publishing is a CI step that runs `helm repo index` and syncs files, and the index is whatever the last job produced. With ChartMuseum, publishing is an HTTP POST and the server maintains the index. The static approach has fewer moving parts and no auth surface to defend; ChartMuseum has an upload API, existence checks via `HEAD`, and a `GET /health` endpoint that returns 200 OK for liveness probes.
The more interesting comparison is Harbor. Harbor is a container registry that also stores charts as OCI artifacts. ChartMuseum is not a registry and the README does not claim to be one. If you already run Harbor for images, adding charts there avoids a second service and a second set of credentials, at the cost of moving your clients to OCI-based commands. If you do not run a registry, or if your tooling and CI templates are built around `helm repo add` and `helm cm-push`, ChartMuseum is the smaller thing to operate. The two are not interchangeable; they are two generations of the same job.
A third option worth naming is the cloud provider's own artifact service. Those exist, and the README does not discuss them. The trade-off is the same one ChartMuseum already made: managed service versus a process you run against a bucket you own.
Maintenance, release cadence and what the licence means for a fork
The repository is not archived, and the last push was on 2026-09-18. Recent releases are v0.16.4 on 2026-02-03, v0.16.5 on 2026-03-24, and v0.16.6 on 2026-08-14. That is a slow but real cadence: roughly two releases in the first eight months of 2026, with version numbers still in the 0.x range. The Makefile even carries a comment noting that the version constant is bumped by hand before releasing, which tells you releases are deliberate rather than continuous.
The practical upgrade cost is low for the server itself. It is a single binary, and the Dockerfile runs it as a non-root user with no shell entrypoint, so replacing the image is the whole upgrade. What does carry cost is the dependency surface. The go.mod file pins helm.sh/helm/v3 at v3.20.2 and pulls in cloud SDKs for GCP, Azure and others as indirect dependencies, plus a large indirect block. Each of those SDKs has its own credential and TLS behaviour. Upgrading ChartMuseum can therefore change how it talks to your object store even when the ChartMuseum code did not change.
On licensing: the repository is Apache-2.0. That is a permissive licence, and it is the same licence Helm itself uses, so there is no mismatch if you vendor or fork. This is not legal advice, and the licence file in the repository root is the authority; if you plan to redistribute a modified build, read LICENSE rather than this paragraph. One thing the README does not document is any support or deprecation policy, so there is no stated window in which an old version keeps receiving fixes.
Editorial conclusion
Adopt ChartMuseum if you need the classic index.yaml repository protocol, an HTTP upload API for CI, and charts stored in a bucket you already pay for. Skip it if your delivery pipeline is already OCI-based, since the README describes no OCI support and a registry gives you that without a second service. Before rollout, verify three things against your own setup: that your storage backend is listed in the README, that you have decided between the local filesystem and a shared backend, and that you know what the /health endpoint reports in your deployment. The last push was on 2026-09-18, so the code is current, but the README does not document rollback or migration between storage backends, and that gap is yours to plan around.
Frequently asked questions
What is ChartMuseum?
It is an open-source Helm Chart Repository server written in Go. It serves the standard index.yaml and chart tarballs that Helm clients expect, and adds an HTTP API for uploading, listing and deleting chart versions.
How does ChartMuseum compare with Harbor?
Harbor is a container registry that also stores charts as OCI artifacts, while ChartMuseum is a Helm Chart Repository server and the README describes no OCI support. If you already run Harbor for images, adding charts there avoids a second service; if your tooling uses helm repo add and helm cm-push, ChartMuseum is the smaller component to run.
What are the alternatives to ChartMuseum?
The simplest alternative is a static bucket or web host with a generated index.yaml and no server at all, which moves index generation into CI. The other main option is an OCI-based registry, which ChartMuseum does not provide according to the README.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/helm-chartmuseum)