DevCloudLab More courses at DevCloudLab.com →
FLUX CD · SECTION 3 · LECTURE 4

DevCloudLab

(Optional) Creating a private Helm repository

Section 3, Lecture 4, from the Flux CD course by DevCloudLab.


What you’ll learn

Overview

This lecture covers how to set up ChartMuseum, an open-source Helm chart repository server, to create a private repository that requires authentication. You will deploy ChartMuseum using Docker, create a test Helm chart, package it, and push it to the repository.

What is ChartMuseum?

ChartMuseum is a lightweight, self-hosted Helm chart repository server maintained by the Helm community. It allows you to:

Prerequisites

Setting Up ChartMuseum

Create a Docker volume for chart storage

docker volume create my-chartmuseum-storage

This volume persists your charts even if the container is stopped or removed.

Run the ChartMuseum container

docker run -d \
  --name my-helm-repo \
  -p 8080:8080 \
  -v my-chartmuseum-storage:/charts \
  -u 0 \
  -e STORAGE=local \
  -e STORAGE_LOCAL_ROOTDIR=/charts \
  -e ALLOW_OVERWRITE=true \
  -e BASIC_AUTH_USER=chartuser \
  -e BASIC_AUTH_PASS=mypass \
  ghcr.io/helm/chartmuseum:v0.16.6

The image comes from the project’s own GitHub Container Registry. The older chartmuseum/chartmuseum repository on Docker Hub was last pushed in January 2021 and still ships ChartMuseum 0.12.0, so do not use it.

This command runs ChartMuseum in the background. The key flags are:

Creating and Pushing a Test Chart

Create a Helm chart scaffold

helm create busybox
cd busybox

Modify the deployment template

Edit templates/deployment.yaml. In the spec.template.spec.containers section, replace the container definition with:

      containers:
        - name: 
          securityContext:
          image: ":"
          imagePullPolicy: 
          command:
            - sleep
            - infinity
          resources:

This adds a sleep command to keep the container running indefinitely, because BusyBox has no startup command of its own. The template still reads the image from values; the switch from Nginx to BusyBox happens in values.yaml, next.

Update values.yaml

Edit values.yaml and replace the image section with:

image:
  repository: busybox
  pullPolicy: IfNotPresent
  tag: "latest"

Package the chart

helm package .

This creates busybox-0.1.0.tgz, a compressed archive of the chart.

Push the chart to ChartMuseum

curl -u chartuser --data-binary "@busybox-0.1.0.tgz" http://localhost:8080/api/charts

When prompted, enter the password: mypass. The response confirms the chart was saved to the repository.

Verifying Your Repository

Add the repository to Helm

helm repo add my-helm-repo --username chartuser http://localhost:8080

When prompted, enter the password: mypass.

Search for your chart

helm search repo busybox

Output shows the chart is available in the repository:

NAME                  CHART VERSION  APP VERSION  DESCRIPTION
my-helm-repo/busybox  0.1.0          1.16.0       A Helm chart for Kubernetes

The APP VERSION comes from the appVersion field that helm create wrote into Chart.yaml; we never changed it. A different Helm version may scaffold a different default there, so do not be surprised if your number differs.

Install the chart (example, Helm only)

To install the chart directly with Helm (not using Flux CD):

helm install mybusybox my-helm-repo/busybox

In the next lecture, you will use Flux CD to deploy this chart instead.

Complete command reference

Docker: Run ChartMuseum with basic authentication

docker run -d \
  --name my-helm-repo \
  -p 8080:8080 \
  -v my-chartmuseum-storage:/charts \
  -u 0 \
  -e STORAGE=local \
  -e STORAGE_LOCAL_ROOTDIR=/charts \
  -e ALLOW_OVERWRITE=true \
  -e BASIC_AUTH_USER=chartuser \
  -e BASIC_AUTH_PASS=mypass \
  ghcr.io/helm/chartmuseum:v0.16.6

Helm: Create and package a chart

helm create busybox
cd busybox
helm package .

Helm: Add an authenticated repository

helm repo add my-helm-repo --username chartuser http://localhost:8080

When prompted, enter: mypass

Helm: Search and display available charts

helm search repo busybox

Curl: Push a chart package to ChartMuseum

curl -u chartuser --data-binary "@busybox-0.1.0.tgz" http://localhost:8080/api/charts

Password: mypass

Full manifest examples

templates/deployment.yaml (container section)

      containers:
        - name: 
          securityContext:
          image: ":"
          imagePullPolicy: 
          command:
            - sleep
            - infinity
          resources:

values.yaml (image section)

image:
  repository: busybox
  pullPolicy: IfNotPresent
  tag: "latest"

Troubleshooting

ChartMuseum image fails to pull

Verify the official image is available:

docker pull ghcr.io/helm/chartmuseum:v0.16.6

The ChartMuseum project publishes its images on the GitHub Container Registry and no longer updates the old chartmuseum/chartmuseum repository on Docker Hub. The GHCR image needs no login to pull.

Chart push fails with permission denied and HTTP 500

{"error":"open /charts/busybox-0.1.0.tgz: permission denied"}

The -u 0 flag is missing from docker run. Remove the container and start it again with the flag in place (the volume can stay):

docker rm -f my-helm-repo

Chart push fails with connection refused

Verify the container is running:

docker ps | grep my-helm-repo

Check the container logs:

docker logs my-helm-repo

Authentication fails when adding the repository

Verify credentials:

These must match the environment variables BASIC_AUTH_USER and BASIC_AUTH_PASS.

helm search repo returns no results

Refresh the local repository index:

helm repo update

Cleaning up

To remove ChartMuseum and reset your environment:

docker stop my-helm-repo
docker rm my-helm-repo
docker volume rm my-chartmuseum-storage
rm -rf ~/busybox
rm -f ~/busybox-0.1.0.tgz
helm repo remove my-helm-repo

Further reading

Next steps

With your private ChartMuseum repository running, you are ready to integrate it with Flux CD. In the next lecture, you will configure a HelmRepository resource to tell Flux CD about your private repository, and use a HelmRelease to deploy charts from it.


DevCloudLab

Built by DevCloudLab
Hands-on cloud-native courses: Kubernetes, GitOps, CI/CD and the cloud.
Visit DevCloudLab.com →