Helm Repository Management: ChartMuseum and Harbor

Set up and manage private Helm chart repositories using ChartMuseum and Harbor, plus best practices for working with public chart repositories.

published: reading time: 20 min read author: GeekWorkBench

Introduction

Helm charts become useful only when you can share them across teams and environments. A chart repository is a web server that serves packaged charts and an index file, letting other engineers install your charts with a single command. Without a repository, you are manually copying chart tarballs or relying on local paths, neither of which scales.

Private chart repositories matter for most organizations that build internal platform components. Database operators, messaging middleware, monitoring agents, and shared services need a controlled distribution mechanism with access control, versioning, and audit trails. Public repositories like Bitnami work well for off-the-shelf software, but internal charts require a private solution that stays behind your VPN or works in air-gapped environments.

This guide covers setting up ChartMuseum for lightweight single-team use and Harbor for enterprise environments that already manage container images. You will learn how to push charts, manage versions, configure authentication, mirror public charts for air-gapped clusters, and monitor repository health. By the end, you will have a working private chart repository and the knowledge to operate it in production.

When to Use / When Not to Use

When to use private chart repositories

Private repos make sense when you have internal platform components that should not be public. Database operators, messaging middleware, monitoring stacks, and shared services that your teams install repeatedly benefit from a private repo with controlled access.

A private repo also helps when you need fine-grained access control. Harbor lets you set permissions per project, so one team cannot accidentally install another team’s charts.

Air-gapped environments essentially require private repos since your clusters cannot reach public chart repositories.

When to skip private repos

If you are a solo developer or small team shipping a single service, the operational overhead of maintaining ChartMuseum or Harbor is probably not worth it. A GitHub release with manually downloadable chart tarballs works fine for months.

If your organization already standardized on a different packaging system like ArgoCD ApplicationSets or raw kubectl with kustomize, adding Helm repos on top creates redundancy without clear benefit.

Repository Architecture Flow

flowchart LR
    A[Developer] -->|helm package| B[CI/CD Pipeline]
    B --> C{Push method}
    C -->|OCI| D[Harbor<br/>Chart Registry]
    C -->|HTTP API| E[ChartMuseum<br/>HTTP Server]
    E --> F[index.yaml]
    D --> G[Clusters pull<br/>via helm repo add]
    F --> G

Chart Repository Basics

A Helm chart repository is simply a web server with an index.yaml file listing available charts and their tarballs. Users add your repo and Helm fetches the index:

helm repo add mycorp https://charts.mycorp.example.com
helm repo update
helm install mycorp/app ./mychart

The index.yaml contains chart metadata:

apiVersion: v2
entries:
  myapp:
    - version: 1.0.0
      appVersion: "2.0"
      created: "2026-01-15T10:30:00Z"
      digest: sha256:a1b2c3d4e5f6...
      urls:
        - https://charts.mycorp.example.com/mychart-1.0.0.tgz
    - version: 0.9.0
      appVersion: "1.9"
      created: "2025-12-01T08:00:00Z"
      digest: sha256:b2c3d4e5f6a7...
      urls:
        - https://charts.mycorp.example.com/mychart-0.9.0.tgz

ChartMuseum Installation and Configuration

ChartMuseum is a lightweight, open-source chart repository server written in Go.

Deploy with Helm:

helm repo add stable https://charts.helm.sh/stable
helm repo update
helm install chartmuseum stable/chartmuseum \
  --namespace chartmuseum \
  --create-namespace \
  --set persistence.enabled=true \
  --set persistence.size=10Gi \
  --set env.open.STORAGE=local \
  --set service.type=LoadBalancer

Configuration options:

# Override values
env:
  open:
    STORAGE: local
    STORAGE_LOCAL_ROOTDIR: /charts
    DISABLE_API: "false"
    AUTH_ANONYMOUS_GET: "true"
    CHART_URL: https://charts.mycorp.example.com
    ALLOWED_IMAGE_TYPES: images+helm-chart

persistence:
  enabled: true
  size: 50Gi
  storageClass: standard-ssd

service:
  type: ClusterIP

Upload charts via curl:

# Basic upload
curl -F "chart=@mychart-1.0.0.tgz" http://chartmuseum:8080/api/charts

# With basic auth
curl -u user:pass -F "chart=@mychart-1.0.0.tgz" \
  http://chartmuseum:8080/api/charts

Automated upload in CI/CD:

#!/bin/bash
CHART_VERSION=$(helm show chart ./mychart | grep ^version: | awk '{print $2}')
helm package ./mychart
curl -u "$CHARTMUSEUM_USER:$CHARTMUSEUM_PASS" \
  -F "chart=@mychart-${CHART_VERSION}.tgz" \
  "$CHARTMUSEUM_URL/api/charts"

Harbor as Chart Registry

Harbor is an enterprise-grade registry that handles container images and Helm charts together. If you already use Harbor for container images, extending it for charts provides unified artifact management.

Enable chart repository in Harbor:

  1. Go to Administration > Registries > New endpoint
  2. Select Helm as the provider
  3. Configure the chart repository URL

Or enable via Harbor configuration in /etc/harbor/harbor.yml:

chart:
  absolute_url: true
  compression_rules:
    - name: gzip
      enabled: true
cache_duration: 24h

Push charts to Harbor:

# Login to Harbor
helm registry login harbor.mycorp.example.com

# Push chart directly as OCI artifact
helm chart push harbor.mycorp.example.com/myproject/mychart:1.0.0

# Or use http protocol
helm repo add mycorp https://harbor.mycorp.example.com/chartrepo/myproject
helm repo push ./mychart-1.0.0.tgz mycorp

Chart caching for air-gapped environments:

# Mirror a public chart to your private Harbor
helm chart pull stable/nginx
helm chart export stable/nginx mycorp/charts/
helm chart push mycorp/charts/nginx-1.0.0.tgz mycorp

Repository Caching Strategies

For organizations with multiple clusters or limited internet access, caching public charts locally improves reliability and speed.

ChartMuseum with cache:

# Pull and cache upstream charts
curl https://charts.helm.sh/stable/index.yaml -o /tmp/stable-index.yaml
curl https://charts.bitnami.com/index.yaml -o /tmp/bitnami-index.yaml

# Import into your ChartMuseum
curl -X POST http://mycache:8080/api/charts \
  -F "chart=@/tmp/stable-index.yaml"

Sync automation script:

#!/bin/bash
# sync-charts.sh
UPSTREAM_REPOS="stable bitnami incubator"
CACHE_URL="http://chartmuseum:8080"

for repo in $UPSTREAM_REPOS; do
  echo "Syncing $repo..."
  helm repo add $repo https://charts.$repo.example.com
  helm repo update $repo

  # Get all chart versions
  for chart in $(helm search repo $repo/ --format "{{.Name}}"); do
    helm pull $chart -d /tmp/charts/
  done

  # Push to cache
  for tgz in /tmp/charts/*.tgz; do
    curl -F "chart=@$tgz" $CACHE_URL/api/charts
  done
done

Chart Versioning and Deprecation

Managing chart lifecycles requires clear versioning policies and deprecation signals.

Version policies:

Version TypeFormatUse
Major2.0.0Breaking changes
Minor1.5.0New features, backward compatible
Patch1.4.1Bug fixes

Marking charts as deprecated:

# Chart.yaml
apiVersion: v2
name: old-chart
deprecated: true
version: 1.0.0

Helm treats deprecated charts specially:

# Search shows deprecated status
$ helm search repo mycorp/

NAME                    VERSION     APP VERSION   DEPRECATED
mycorp/old-chart        1.0.0       1.0           true

Automated deprecation notices:

# templates/notes.yaml
{{- if .Chart.Deprecated }}
WARNING: This chart is deprecated and will not receive updates.
Please migrate to: https://charts.mycorp.example.com/new-chart
{{- end }}

Private vs Public Chart Tradeoffs

When deciding between private and public repositories, consider these factors:

FactorPrivate RepositoryPublic Repository
Access ControlFine-grained permissionsLimited
Internet DependencyNone (air-gapped friendly)Requires internet
MaintenanceYour responsibilityManaged by provider
DiscoveryTeam-onlyAnyone can find
ComplianceFull controlMay have restrictions

For most enterprise workloads, a private repository behind your VPN or in an air-gapped environment provides the best balance of security and usability. Public repositories work well for widely-adopted off-the-shelf software like nginx, Redis, or Prometheus where you want the convenience of community-maintained packages.

Production Failure Scenarios

Stale index.yaml after adding new charts

If you push a new chart version to ChartMuseum but forget to regenerate the index.yaml, users running helm repo update will not see the new version. Helm caches the index until the next update.

# After pushing a chart, regenerate index
helm repo index /path/to/charts --url https://charts.mycorp.example.com
# Then commit and push the updated index.yaml

ChartMuseum with API enabled handles this automatically when you use curl -F "chart=@..." to push.

Authentication expiring in CI

Long-running CI pipelines that pull charts hours after authenticating may fail when the Harbor or ChartMuseum token expires. Use short-lived tokens or re-authenticate before each pull.

# Re-authenticate before chart pull in long pipelines
helm registry login --username "$HARBOR_USER" --password "$HARBOR_PASS" harbor.mycorp.example.com
helm pull mycorp/mychart --version 1.0.0

Storage fills up on ChartMuseum

Without monitoring, ChartMuseum storage grows unbounded as you push new chart versions. Old versions accumulate, and if you use local storage, the disk eventually fills.

Set up storage cleanup policies or use an external object store (S3, GCS) with lifecycle policies to automatically delete old chart tarballs.

Harbor OCI vs repository mode confusion

Harbor supports charts in two modes: as OCI artifacts and as traditional chart repositories. Mixing modes or pushing OCI charts to a non-OCI project causes confusing errors.

Ensure your Harbor project has OCI artifact support enabled before pushing chart OCI artifacts.

Common Pitfalls / Anti-Patterns

No index.yaml regeneration

Pushing chart tarballs directly to the web server directory without regenerating index.yaml leaves the repository broken. Helm cannot discover charts that are not listed in the index.

Always regenerate index.yaml after adding or updating charts:

helm repo index /path/to/charts

Using latest tag in chart references

Referring to myapp:latest in your chart repository means Helm always pulls whatever was most recently pushed. This breaks reproducibility and makes rollbacks impossible since you cannot tell which version “latest” actually was.

Always pin to specific versions.

No access control on ChartMuseum

Leaving ChartMuseum with anonymous write access means anyone can upload any chart, including malicious ones. Use authentication and role-based access control.

Not mirroring critical public charts

Relying on public repositories like Bitnami without a local mirror means your air-gapped clusters cannot install those charts when the internet is unavailable. Mirror the charts you depend on.

Mixing chart sources without vetting

Not all public charts are created equal. Charts from unknown sources may have misconfigured resources, outdated dependencies, or security vulnerabilities. Vet public charts before recommending them to your team.

Observability Hooks

Track the health of your chart repository infrastructure with these monitoring practices.

Key metrics to monitor:

# ChartMuseum storage usage (bytes)
chartmuseum_storage_used_bytes

# Repository API request rate
sum(rate(chartmuseum_http_requests_total[5m])) by (method, status)

# Chart download latency
histogram_quantile(0.95, sum(rate(chartmuseum_request_duration_seconds_bucket[5m])) by (le))

# Harbor chart registry storage
harbor_chart_storage_used_bytes{project=~".*"}

# OCI artifact pull failures
sum(rate(oci_manifest_pulls_failed_total[5m])) by (repository, error_code)

Alert rules for chart repositories:

# Alert if ChartMuseum storage is above 80%
- alert: ChartMuseumStorageHigh
  expr: chartmuseum_storage_used_bytes / chartmuseum_storage_limit_bytes > 0.8
  labels:
    severity: warning
  annotations:
    summary: "ChartMuseum storage above 80%"
    description: "Chart repository storage is running low. Consider cleanup or expansion."

# Alert if Harbor chart registry is unavailable
- alert: HarborChartRegistryDown
  expr: harbor_chart_registry_up == 0
  labels:
    severity: critical
  annotations:
    summary: "Harbor chart registry is down"
    description: "Chart artifacts cannot be pulled from Harbor. Check Harbor status."

# Alert on high API error rate
- alert: ChartRepoHighErrorRate
  expr: sum(rate(chartmuseum_http_requests_total{status=~"5.."}[5m])) / sum(rate(chartmuseum_http_requests_total[5m])) > 0.05
  labels:
    severity: warning
  annotations:
    summary: "Chart repository API error rate above 5%"
    description: "High error rate on chart repository API. Check ChartMuseum logs."

Debugging commands:

# Check ChartMuseum health
curl http://chartmuseum:8080/health

# List all charts in ChartMuseum
curl http://chartmuseum:8080/api/charts | jq 'keys'

# Verify Harbor chart repository connectivity
helm repo add mycorp https://harbor.mycorp.example.com/chartrepo/myproject --debug

# Check OCI artifact manifest
oras manifest fetch myregistry.azurecr.io/myteam/mychart:1.0.0

# Verify chart signature
helm verify ./mychart-1.0.0.tgz

Interview Questions

1. What are the key differences between ChartMuseum and Harbor for Helm chart repository management?

Expected answer points:

  • ChartMuseum is a lightweight, Go-based HTTP server specifically for Helm charts with a simple API
  • Harbor is an enterprise-grade registry handling both container images and Helm charts with integrated authentication, scanning, and replication
  • Choose ChartMuseum for single-team, simple chart hosting; Harbor for multi-team enterprise environments already using Harbor for container images
  • Harbor supports both OCI artifact mode and traditional chart repository mode; ChartMuseum uses HTTP API only
2. How do you handle chart deprecation in a private repository?

Expected answer points:

  • Set `deprecated: true` in Chart.yaml—Helm marks the chart as deprecated when users search
  • Add warning notes in templates/notes.yaml that redirect users to the replacement chart
  • Do not delete the old chart—existing installs need to continue working until users migrate
  • Consider keeping old versions available but removing them from search results over time
3. What are the main failure scenarios when running a private Helm chart repository?

Expected answer points:

  • Stale index.yaml—when pushing a new chart version but forgetting to regenerate index, users do not see the new version
  • ChartMuseum with API enabled handles index regeneration automatically via `curl -F "chart=@..."`
  • Storage fills up on ChartMuseum without monitoring—old versions accumulate on local storage until disk fills
  • Authentication expiring in CI—long-running pipelines may fail when Harbor/ChartMuseum tokens expire
4. How do you mirror public charts for air-gapped environments?

Expected answer points:

  • Use `helm chart pull` to download public charts, then `helm chart export` to extract the tarball
  • Push the extracted chart to your private Harbor or ChartMuseum instance
  • Automation script loops through upstream repos, pulls all chart versions, and pushes to cache
  • Set up sync jobs to periodically check for new versions of critical public charts
5. What is the purpose of the index.yaml file in a Helm chart repository?

Expected answer points:

  • index.yaml is the metadata file listing all available charts and their versions in the repository
  • Contains chart metadata: version, appVersion, created date, digest, and URLs to tarballs
  • When users run `helm repo update`, Helm downloads the index.yaml to know what charts/versions are available
  • Must be regenerated after adding or updating charts if not using ChartMuseum API
6. What authentication strategies work for ChartMuseum in CI/CD pipelines?

Expected answer points:

  • Basic auth with username/password passed via environment variables
  • Use short-lived tokens for CI instead of long-lived credentials—re-authenticate before each pull
  • ChartMuseum supports anonymous GET when `AUTH_ANONYMOUS_GET: "true"` is set for public charts
  • For Harbor, use `helm registry login` with credentials stored as secrets in your CI system
7. How does OCI artifact mode in Harbor differ from traditional chart repository mode?

Expected answer points:

  • OCI mode pushes charts as OCI artifacts using `helm chart push` (Helm 3.8+), integrated with container image storage
  • Traditional mode uses HTTP API with index.yaml and chart tarballs via `helm repo add` and `helm repo push`
  • OCI mode requires OCI artifact support enabled at the Harbor project level—disabled by default
  • Mixing modes or pushing OCI charts to a non-OCI project causes confusing errors
8. What metrics should you monitor for Helm chart repository health?

Expected answer points:

  • ChartMuseum storage usage (bytes and percentage of limit)
  • Repository API request rate by method and status code
  • Chart download latency p95
  • Harbor chart registry storage by project
  • OCI manifest pull failures by repository and error code
9. What are the tradeoffs between private and public Helm chart repositories?

Expected answer points:

  • Private repos offer fine-grained access control, no internet dependency (air-gapped friendly), full compliance control
  • Private repos require your own maintenance—updates, security patches, storage management
  • Public repos (Bitnami, etc.) are convenient for off-the-shelf software but require internet access and provide limited access control
  • For enterprise workloads with security/compliance requirements, private repos behind VPN are usually the right choice
10. How do you handle chart versioning and semantic version conventions?

Expected answer points:

  • Follow semantic versioning: Major (breaking changes), Minor (new features backward compatible), Patch (bug fixes)
  • Major version bumps indicate incompatible API or configuration changes
  • Mark deprecated charts with `deprecated: true` in Chart.yaml
  • Keep old versions available for existing users while clearly communicating migration paths
11. What are the security implications of using public Helm chart repositories and how do you mitigate them?

Expected answer points:

  • Public charts from unknown sources may contain misconfigured resources, outdated dependencies, or security vulnerabilities
  • Vet public charts before recommending them to your team — review Chart.yaml, values schema, templates
  • Mirror critical public charts to your private repository to avoid dependency on external availability
  • Charts can contain pre-install hooks that run arbitrary code — review hooks before use
  • Use Helm registry authentication and signed charts to verify chart authenticity
  • Regularly update mirrored charts to patch known vulnerabilities in dependencies
12. How do you migrate from ChartMuseum to Harbor for chart repository management?

Expected answer points:

  • Harbor supports both OCI artifact mode and traditional chart repository mode — ensure you understand which mode you're migrating to
  • Export charts from ChartMuseum: pull all chart versions with `helm pull chartmuseum/mychart`
  • Push to Harbor: either via `helm chart push` (OCI mode) or `helm repo push` (HTTP mode)
  • Update CI/CD pipelines to reference new Harbor repository URL
  • Update developer workstation configurations: `helm repo remove chartmuseum && helm repo add harbor`
  • Keep ChartMuseum running during transition period — remove after verifying Harbor is working for all users
13. What is the role of chart signing and how do you implement it in a private repository?

Expected answer points:

  • Chart signing uses PGP private keys to sign chart packages, providing authenticity and integrity verification
  • Sign charts as part of CI/CD pipeline after packaging: `helm sign mychart-1.0.0.tgz`
  • Distribute public key to users: via key server, direct exchange, or embedded in internal documentation
  • Users verify: `helm verify mychart-1.0.0.tgz` or `helm install --verify mychart`
  • Harbor supports chart signing natively; ChartMuseum requires external signing integration
  • Signing prevents tampered charts from being installed — critical for supply chain security
14. How do you handle chart repository storage management and cleanup of old versions?

Expected answer points:

  • Monitor ChartMuseum storage usage — set alerts at 70% capacity to avoid running out of space
  • Implement retention policy: keep N recent versions per chart, archive or delete older versions
  • Use object store (S3, GCS) with lifecycle policies to auto-delete old chart tarballs after specified period
  • Before deleting old versions: ensure no active deployments depend on those versions
  • Announce deprecation of old versions in chart repository notices — give users time to update
  • Archive rather than delete: download and store old chart versions in cold storage for compliance if needed
15. What are the differences between Helm chart repository modes and OCI artifact distribution?

Expected answer points:

  • Traditional chart repository uses HTTP API with index.yaml and chart tarballs — `helm repo add`, `helm repo update`
  • OCI artifact distribution uses `helm chart push/pull` to push charts as OCI artifacts to container registries
  • OCI mode integrates chart storage with container image storage — single registry for both
  • OCI requires Helm 3.8+ and registry support for OCI artifacts — Harbor supports this, basic ChartMuseum does not
  • Migrating between modes is not automatic — choose mode based on your registry capabilities and team workflow
16. How do you implement chart repository access control for multiple teams using Harbor?

Expected answer points:

  • Harbor uses project-based access control — each team has their own project with isolated chart repositories
  • Project members: can push/pull charts within project; non-members cannot access
  • Robot accounts: create service accounts for CI/CD with specific project permissions — avoid sharing user credentials
  • Use LDAP/AD integration to sync team memberships from corporate directory
  • Public projects: anyone can pull charts without authentication — use for shared base charts
  • Quotas: set storage limits per project to prevent one team from consuming all repository space
17. How do you test Helm charts before publishing to a production chart repository?

Expected answer points:

  • Chart testing: `helm lint` validates syntax and template rendering; `helm template` renders without installing
  • Install in test cluster: `helm install mychart ./mychart --namespace test --dry-run --debug`
  • Use `helm unittest` plugin for unit tests inside charts — test template output for various input values
  • CI/CD pipeline: lint, template, install to ephemeral test namespace, run smoke tests, uninstall
  • Test upgrade path: install old version, upgrade to new version, verify upgrade completes without errors
  • Test rollback: install version, upgrade, then rollback — verify rollback restores previous state
18. What is the purpose of chart provenance files and how do you use them in a supply chain?

Expected answer points:

  • Provenance files (prov files) are SHA256 checksums for chart packages, signed with PGP
  • Generated with `helm package --sign` and verified with `helm verify`
  • Prov files enable users to verify chart integrity and authenticity before installation
  • In supply chain: sign chart in CI/CD, distribute prov file alongside chart tarball, users verify before install
  • Harbor integrates with Notary for chart signing and verification
  • Prov files protect against tampered charts being deployed to production clusters
19. How do you handle chart dependencies and ensure reproducible installs across environments?

Expected answer points:

  • Charts can declare dependencies in Chart.yaml with version constraints
  • `helm dependency update` fetches dependencies into charts/ directory before packaging
  • Pin specific versions in requirements.lock for reproducible installs — commit lock file to source control
  • Test that `helm install` works offline with only local chart package — dependencies must be bundled
  • If using private chart dependencies, ensure repository containing dependency is added before installing
  • Renovate or similar tools can automatically update chart dependencies when new versions are available
20. What monitoring and alerting should you configure for a production Helm chart repository?

Expected answer points:

  • ChartMuseum storage usage: alert when >80% of storage limit consumed
  • API error rate: alert when 5xx errors exceed threshold — indicates server issues or malformed requests
  • API latency: p95 latency above 500ms may indicate performance problems under load
  • Harbor chart registry health: alert if Harbor is down — chart pulls will fail across all clusters
  • Failed uploads: track failed `curl -F "chart=@..."` requests — indicates authentication or permission issues
  • Queue depth for async chart sync jobs: if jobs accumulate, upstream sync is lagging

Further Reading

Conclusion

Key Takeaways

  • ChartMuseum works for lightweight single-team use; Harbor suits enterprise multi-team environments with image registry needs
  • Always regenerate index.yaml after pushing charts
  • Mirror public charts you depend on if you operate in air-gapped environments
  • Authentication tokens in CI need to be refreshed for long pipelines
  • Harbor supports both OCI artifact mode and traditional chart repository mode; know which your project uses

Repository Checklist

# Add your private repo
helm repo add mycorp https://charts.mycorp.example.com
helm repo update

# Verify a chart is available
helm search repo mycorp/

# Pull a specific version
helm pull mycorp/mychart --version 1.0.0

# Check for deprecated charts
helm repo update
helm search repo mycorp/ --deployed

Category

Related Posts

Developing Helm Charts: Templates, Values, and Testing

Create production-ready Helm charts with Go templates, custom value schemas, and testing using Helm unittest and ct.

#helm #kubernetes #devops

Helm Versioning and Rollback: Managing Application Releases

Master Helm release management—revision history, automated rollbacks, rollback strategies, and handling failed releases gracefully.

#helm #kubernetes #devops

OCI Artifacts: Distributing Container Images and Helm Charts

Package and distribute container images, Helm charts, and other artifacts using the OCI (Open Container Initiative) specification for portable artifact management.

#oci #containers #helm