$linuxjunkies
>

Use Helm Charts on Linux

Install Helm 3, manage chart repos, override values, render manifests locally with helm template, and package your own chart for Kubernetes.

IntermediateUbuntuDebianFedoraArch10 min readUpdated June 7, 2026

Before you start

  • A running Kubernetes cluster (minikube, kind, or remote)
  • kubectl installed and configured with a valid kubeconfig
  • sudo or root access for package installation
  • Internet access to reach chart repositories and OCI registries

Helm is the de-facto package manager for Kubernetes. A Helm chart bundles all the Kubernetes manifests, defaults, and lifecycle hooks a workload needs into a single versioned artefact. This guide covers adding repos, installing and upgrading releases, overriding values, using helm template for local rendering, and packaging your own chart from scratch.

Prerequisites

  • A working Kubernetes cluster (local via minikube, kind, or a remote cluster)
  • kubectl configured with a valid ~/.kube/config
  • Helm 3 installed (see below)
  • Internet access to pull chart repositories

Installing Helm 3

Helm 3 dropped the server-side Tiller component entirely. All state is stored as Kubernetes Secrets inside your cluster. Install it from your distro's package manager or the official script.

Debian / Ubuntu

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" \
  | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt update && sudo apt install helm -y

Fedora / RHEL / Rocky

sudo dnf install helm -y

On RHEL 8/9 you may need the EPEL repository enabled first: sudo dnf install epel-release -y.

Arch Linux

sudo pacman -S helm

Verify the installation

helm version

Output will look similar to: version.BuildInfo{Version:"v3.14.x", ...}. Anything 3.x is fine for this guide.

Working with Chart Repositories

Helm repositories are simple HTTPS endpoints serving an index.yaml and chart tarballs. You manage them with helm repo.

Add and update repos

# Add the Bitnami repo as an example
helm repo add bitnami https://charts.bitnami.com/bitnami

# Add the official stable repo (community-maintained)
helm repo add stable https://charts.helm.sh/stable

# Sync local index cache from all configured repos
helm repo update

Search for charts

# Search across all added repos
helm search repo nginx

# Search Artifact Hub (the public index of public repos)
helm search hub postgresql

Inspect a chart before installing

helm show chart bitnami/nginx
helm show values bitnami/nginx

helm show values prints every configurable parameter with its default. Pipe it to a file when you want a full reference to edit from.

Installing and Upgrading Releases

A release is a named deployment of a chart into a namespace. Helm tracks each release's history as versioned Secrets.

Basic install

helm install my-nginx bitnami/nginx \
  --namespace webapps \
  --create-namespace

Override values inline

helm install my-nginx bitnami/nginx \
  --namespace webapps \
  --create-namespace \
  --set service.type=ClusterIP \
  --set replicaCount=2

Chaining --set flags works for simple scalar values. For nested keys use dot notation: --set ingress.enabled=true. For anything more complex, use a values file.

Override values with a file

# Dump defaults to a starting file
helm show values bitnami/nginx > my-values.yaml

# Edit what you need, then install
helm install my-nginx bitnami/nginx \
  --namespace webapps \
  --create-namespace \
  -f my-values.yaml

You can layer multiple -f files; later files take precedence. This is useful for a base values file plus an environment-specific override.

Upgrade a release

helm upgrade my-nginx bitnami/nginx \
  --namespace webapps \
  -f my-values.yaml \
  --version 15.4.0

Upgrade or install in one command

helm upgrade --install my-nginx bitnami/nginx \
  --namespace webapps \
  --create-namespace \
  -f my-values.yaml

This pattern is common in CI/CD pipelines because it is idempotent.

View release history and roll back

helm history my-nginx -n webapps
helm rollback my-nginx 1 -n webapps

Rendering Manifests Locally with helm template

helm template renders a chart to plain YAML without touching the cluster. Use it to inspect what Helm will actually send to the API server, feed output to kubectl diff, or integrate with GitOps tools like Flux or Argo CD.

helm template my-nginx bitnami/nginx \
  --namespace webapps \
  -f my-values.yaml \
  > rendered-manifests.yaml
# Diff against the live cluster state
helm template my-nginx bitnami/nginx -f my-values.yaml -n webapps \
  | kubectl diff -f - -n webapps

Important: helm template skips cluster validation and hook logic. It is a rendering tool, not a dry-run substitute for all purposes. Use helm upgrade --dry-run --debug when you also want server-side validation.

helm upgrade --install my-nginx bitnami/nginx \
  --namespace webapps \
  -f my-values.yaml \
  --dry-run --debug 2>&1 | less

Packaging Your Own Chart

Creating a chart is straightforward. The scaffold gives you a working example you then adapt.

Scaffold a new chart

helm create mychart

This produces a directory tree:

mychart/
  Chart.yaml          # metadata: name, version, appVersion
  values.yaml         # default values
  charts/             # chart dependencies live here
  templates/          # Go-template Kubernetes manifests
    deployment.yaml
    service.yaml
    ingress.yaml
    _helpers.tpl      # reusable named templates
    NOTES.txt         # printed after helm install

Edit Chart.yaml

cat mychart/Chart.yaml

Set version (the chart version, semver) and appVersion (the upstream app version) appropriately. These are separate fields intentionally.

Edit values.yaml and templates

Define your configurable parameters in values.yaml with sensible defaults. Reference them inside templates using {{ .Values.myKey }}. Use _helpers.tpl for label blocks and name helpers shared across templates to keep things DRY.

Lint and test render

# Lint for common errors
helm lint mychart/

# Render locally to check output
helm template my-release mychart/ -f mychart/values.yaml

Declare dependencies

If your chart depends on another (e.g., PostgreSQL), declare it in Chart.yaml:

dependencies:
  - name: postgresql
    version: "13.x.x"
    repository: https://charts.bitnami.com/bitnami
# Download declared dependencies into charts/
helm dependency update mychart/

Package and push

# Creates mychart-0.1.0.tgz
helm package mychart/

# Push to an OCI registry (Helm 3.8+)
helm push mychart-0.1.0.tgz oci://registry.example.com/helm-charts

OCI registries (Docker Hub, GitHub Container Registry, AWS ECR, Harbor) are the modern distribution method. Classic HTTP repos served by chartmuseum still work but OCI is the recommended path going forward.

Verification

# List all releases across all namespaces
helm list -A

# Show the status of a specific release
helm status my-nginx -n webapps

# Confirm Kubernetes objects are running
kubectl get all -n webapps

Troubleshooting

  • "Error: INSTALLATION FAILED: cannot re-use a name that is still in use" — A release with that name already exists. Use helm upgrade --install or helm uninstall first.
  • Values not taking effect — Later -f files and --set flags override earlier ones. Run helm get values <release> -n <ns> to see the merged values actually applied.
  • Outdated chart versions in search — Run helm repo update to refresh the local index cache.
  • Template render errors — Run helm template --debug to see the partially rendered output alongside the error location.
  • Dependency not found — Run helm dependency update inside the chart directory before packaging or installing locally.
tested on:Ubuntu 24.04Fedora 40Arch rollingRocky 9

Frequently asked questions

What is the difference between helm install and helm upgrade --install?
helm install fails if a release with that name already exists. helm upgrade --install is idempotent: it installs on first run and upgrades on subsequent runs, making it safe for CI/CD pipelines.
How do I see the final merged values applied to a live release?
Run helm get values <release> -n <namespace>. Add --all to include default values that were not overridden.
Is helm template a safe dry run?
It renders templates locally without cluster access, so it skips server-side validation and hook execution. For a true dry run that validates against the API server, use helm upgrade --install --dry-run --debug.
Can I use Helm without a Kubernetes cluster for templating?
Yes. helm template works entirely offline against local chart files. Some charts use lookup functions that query the cluster; those return empty results when no cluster is reachable, so keep that in mind.
What is the difference between chart version and appVersion in Chart.yaml?
version is the version of the Helm chart itself and follows semver. appVersion is the version of the upstream application being packaged (e.g., nginx 1.25.3). They are independent and should be bumped separately.

Related guides