How to Install Helm on Ubuntu 26.04 LTS (Complete Guide 2026)
Table of Contents
- What is Helm and Why You Need It
- Helm 2 vs Helm 3: The Critical Difference (Tiller is Gone)
- Prerequisites
- Method 1: Install via APT Repository (Recommended)
- Method 2: Install via Script (Quickest)
- Method 3: Install via Snap
- Method 4: Install Manually from Binary
- Verify the Installation
- Configure Shell Autocompletion
- Managing Helm Repositories
- Essential Helm Commands Cheatsheet
- Install Your First Application with Helm
- Upgrade, Rollback, and Uninstall
- Create Your First Helm Chart
- OCI Registry Support
- The helm diff Plugin: Preview Before Upgrade
- Helm in CI/CD Pipelines
- Helm 4.0: What’s Coming in September 2026
- Common Issues and Quick Fixes
- Next Steps
Every time you install something complex on Kubernetes — an ingress controller, a monitoring stack, a database — you’re managing dozens of YAML files that need to be applied in the right order with the right values. Change one environment (dev to staging to production) and you’re editing the same files in parallel, hoping they stay in sync. Helm solves this by treating Kubernetes applications as versioned, configurable packages — the same concept as apt for Ubuntu, but for Kubernetes.
What is Helm and Why You Need It
Helm is a package manager for Kubernetes that simplifies the process of defining, installing, and upgrading even the most complex Kubernetes applications. Helm bundles all related Kubernetes resources into a single package called a chart, making it easier to manage and distribute.
Without Helm, deploying a production-grade application to Kubernetes means:
Without Helm:
kubectl apply -f namespace.yaml
kubectl apply -f configmap.yaml
kubectl apply -f secret.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
kubectl apply -f hpa.yaml
# ...repeat for dev, staging, prod with manual value substitution
# No easy rollback if something breaks
With Helm:
helm install my-app ./my-chart -f values-prod.yaml
# All resources applied in correct order
# Values substituted from values file
# Full rollback with: helm rollback my-app
Helm provides several key advantages over plain YAML: templating allows variables and functions in YAML files making them reusable; packaging bundles all related resources into a single chart; versioning allows easier upgrades and rollbacks; and lifecycle management provides commands for installing, upgrading, and uninstalling applications.
A Helm chart is to Kubernetes what a .deb package is to Ubuntu. When you run helm install prometheus prometheus-community/kube-prometheus-stack, Helm fetches the chart, resolves dependencies, substitutes your values, and deploys the complete Prometheus + Grafana + AlertManager stack in a single command.
Helm 2 vs Helm 3: The Critical Difference (Tiller is Gone)
In Helm 2, Tiller was the server-side component responsible for managing releases inside the Kubernetes cluster. Helm 3 removes Tiller entirely. All release management is now performed on the client side, leveraging the user’s kubeconfig and Kubernetes RBAC for authorization.
If you’ve used Helm before and remember running helm init to install Tiller — that’s Helm 2. It’s deprecated. Helm 3 is the only version you should be running in 2026.
Key differences that matter in practice:
| Helm 2 (deprecated) | Helm 3 (current) | |
|---|---|---|
| Tiller | Required (cluster-side component) | Removed entirely |
| Security | Tiller had cluster-admin by default | Uses your kubeconfig RBAC |
| Release storage | ConfigMaps in kube-system | Secrets in the release namespace |
helm init | Required before first use | Not needed — no server-side setup |
| Release name | Optional (--name) | Required positional argument |
| 3-way merge | No | Yes — smarter updates |
| OCI support | No | Yes (stable since Helm 3.8) |
This change simplifies the security model and aligns better with Kubernetes-native access control practices. Helm 3 needs no special cluster permissions beyond what your kubeconfig already grants — if you can kubectl apply, you can helm install.
Prerequisites
- Ubuntu 26.04 LTS (Resolute Raccoon)
- A running Kubernetes cluster — see our Install Kubernetes Cluster on Ubuntu 26.04 guide
kubectlconfigured and connected:kubectl cluster-infoshould succeedcurlandgnupginstalled
Verify kubectl access:
kubectl get nodes
# All nodes should show Ready
kubectl version --client
# Should show v1.36.x
Helm doesn’t need a cluster to install, but it needs one to deploy charts. You can install Helm on any machine that has kubectl access to the cluster.
Method 1: Install via APT Repository (Recommended)
The APT repository method is recommended for Ubuntu because it integrates with system updates and security patches.
# Install prerequisites
sudo apt update
sudo apt install -y curl gnupg apt-transport-https
# Add Helm's official GPG key
curl https://baltocdn.com/helm/signing.asc | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/helm.gpg > /dev/null
# Add Helm stable APT repository
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
# Update package index and install
sudo apt update
sudo apt install -y helm
Advantage of APT method: sudo apt upgrade will automatically update Helm alongside other system packages. This is the cleanest approach for long-running servers where you want security patches applied consistently.
Method 2: Install via Script (Quickest)
The official Helm installer script detects your OS and architecture, downloads the latest stable release, and installs it automatically:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
The script:
- Detects your OS (Linux/macOS/Windows)
- Detects your architecture (amd64/arm64)
- Downloads the latest stable release (v3.21.3 at time of writing)
- Verifies the checksum
- Installs to
/usr/local/bin/helm
For a specific version (useful in CI/CD to pin the Helm version):
DESIRED_VERSION="v3.21.3"
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | \
DESIRED_VERSION=$DESIRED_VERSION bash
Method 3: Install via Snap
The snap package is the fastest way to get Helm up and running on Ubuntu.
sudo snap install helm --classic
The --classic flag is required because Helm needs access to your home directory (for ~/.kube/config) and system paths — beyond what confined snaps allow by default.
Trade-off: Snap packages are containerized and typically larger than the native binary. The snap version may lag slightly behind the latest release. For most use cases this is fine; use APT or the binary method if you need the absolute latest version.
Method 4: Install Manually from Binary
For air-gapped environments or when you need a specific version not yet in the APT repository:
HELM_VERSION="v3.21.3"
ARCH="amd64" # or arm64 for ARM servers
# Download the release archive
curl -LO "https://get.helm.sh/helm-${HELM_VERSION}-linux-${ARCH}.tar.gz"
# Verify checksum
curl -LO "https://get.helm.sh/helm-${HELM_VERSION}-linux-${ARCH}.tar.gz.sha256sum"
sha256sum -c helm-${HELM_VERSION}-linux-${ARCH}.tar.gz.sha256sum
# Expected: helm-v3.21.3-linux-amd64.tar.gz: OK
# Extract and install
tar -zxvf helm-${HELM_VERSION}-linux-${ARCH}.tar.gz
sudo mv linux-${ARCH}/helm /usr/local/bin/helm
sudo chmod +x /usr/local/bin/helm
# Clean up
rm -rf linux-${ARCH} helm-${HELM_VERSION}-linux-${ARCH}.tar.gz*
Always verify the checksum before installing — this protects against corrupted downloads and supply chain attacks.
Verify the Installation
helm version
Expected output:
version.BuildInfo{
Version:"v3.21.3",
GitCommit:"...",
GitTreeState:"clean",
GoVersion:"go1.23.x"
}
Check Helm’s environment configuration:
helm env
# HELM_BIN="helm"
# HELM_CACHE_HOME="/home/user/.cache/helm"
# HELM_CONFIG_HOME="/home/user/.config/helm"
# HELM_DATA_HOME="/home/user/.local/share/helm"
# HELM_DEBUG="false"
# HELM_KUBEAPISERVER=""
# HELM_KUBECAFILE=""
# HELM_KUBECONTEXT=""
# HELM_KUBETOKEN=""
# HELM_MAX_HISTORY="10"
# HELM_NAMESPACE="default"
# HELM_REPOSITORY_CACHE="/home/user/.cache/helm/repository"
# HELM_REPOSITORY_CONFIG="/home/user/.config/helm/repositories.yaml"
Notable defaults: HELM_MAX_HISTORY="10" means Helm keeps only the last 10 release revisions. Increase it if you need deeper rollback history: export HELM_MAX_HISTORY=25
Configure Shell Autocompletion
Helm includes autocompletion for bash, zsh, fish, and PowerShell. Setting this up saves significant time when working with long chart names and release names:
# Bash autocompletion
echo 'source <(helm completion bash)' >> ~/.bashrc
source ~/.bashrc
# Zsh autocompletion
echo 'source <(helm completion zsh)' >> ~/.zshrc
source ~/.zshrc
# Fish shell
helm completion fish > ~/.config/fish/completions/helm.fish
After enabling autocompletion, helm ins<TAB> completes to helm install, and helm install prom<TAB> searches for matching chart names.
Managing Helm Repositories
A Helm repository is a collection of charts hosted at an HTTP endpoint — the equivalent of a Ubuntu PPA. Helm ships with no repositories preconfigured:
# Add popular repositories
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo add jetstack https://charts.jetstack.io # cert-manager
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo add metallb https://metallb.github.io/metallb
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
# Update all repositories (fetch latest chart index)
helm repo update
# List configured repositories
helm repo list
# NAME URL
# bitnami https://charts.bitnami.com/bitnami
# prometheus-community https://prometheus-community.github.io/helm-charts
# ...
# Search for charts across all repositories
helm search repo nginx
# NAME CHART VERSION APP VERSION DESCRIPTION
# bitnami/nginx 18.x.x 1.27.x NGINX Open Source is a web server that...
# ingress-nginx/ingress-nginx 4.x.x 1.11.x Ingress controller for Kubernetes using NGINX
# Search for a specific app version
helm search repo postgresql --versions | head -10
# Remove a repository
helm repo remove stable
Essential Helm Commands Cheatsheet
Master the install/upgrade/rollback lifecycle — these are the commands you use daily.
# ── INSTALLATION ──────────────────────────────────────────────
# Install a chart
helm install <release-name> <chart> [flags]
# Install with custom values file
helm install my-app bitnami/nginx -f values.yaml
# Install with inline value overrides
helm install my-app bitnami/nginx \
--set service.type=NodePort \
--set replicaCount=3
# Install in a specific namespace (create if not exists)
helm install my-app bitnami/nginx \
--namespace my-namespace \
--create-namespace
# Install and wait until all resources are ready
helm install my-app bitnami/nginx --wait --timeout 5m
# Dry run — show what would be installed without applying
helm install my-app bitnami/nginx --dry-run
# ── INSPECTION ────────────────────────────────────────────────
# List all installed releases
helm list -A # -A shows all namespaces
# Show release status
helm status my-app
# Show all resources for a release
helm get all my-app
# Show the values used for a release
helm get values my-app
# Show the rendered YAML templates
helm get manifest my-app
# Show release history
helm history my-app
# ── SEARCH AND INSPECT CHARTS ─────────────────────────────────
# Search repositories
helm search repo redis
# Show chart details and values
helm show chart bitnami/redis
helm show values bitnami/redis
# Render templates locally without installing
helm template my-release bitnami/redis -f values.yaml
# ── UPGRADE ───────────────────────────────────────────────────
# Upgrade an existing release
helm upgrade my-app bitnami/nginx --set replicaCount=5
# Upgrade or install if not already installed
helm upgrade --install my-app bitnami/nginx -f values.yaml
# Upgrade with atomic rollback on failure
helm upgrade --install my-app bitnami/nginx \
--atomic \
--timeout 5m
# ── ROLLBACK ──────────────────────────────────────────────────
# Roll back to the previous revision
helm rollback my-app
# Roll back to a specific revision
helm rollback my-app 2
# View history before rolling back
helm history my-app
# ── UNINSTALL ─────────────────────────────────────────────────
# Uninstall a release (removes all Kubernetes resources)
helm uninstall my-app
# Uninstall but keep history (allows reinstall with rollback)
helm uninstall my-app --keep-history
# ── PLUGINS ───────────────────────────────────────────────────
# Install a plugin
helm plugin install https://github.com/databus23/helm-diff
# List installed plugins
helm plugin list
# Update all plugins
helm plugin update $(helm plugin list | awk 'NR>1 {print $1}')
Install Your First Application with Helm
Deploy NGINX as a real-world example — the same NGINX Ingress Controller used in our NGINX Ingress Controller guide:
# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
# Preview the default values
helm show values ingress-nginx/ingress-nginx | head -50
# Install with 2 replicas and Prometheus metrics enabled
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--create-namespace \
--set controller.replicaCount=2 \
--set controller.metrics.enabled=true \
--wait
# Verify installation
helm list -n ingress-nginx
# NAME NAMESPACE REVISION STATUS CHART
# ingress-nginx ingress-nginx 1 deployed ingress-nginx-4.x.x
helm status ingress-nginx -n ingress-nginx
Install the Prometheus + Grafana monitoring stack (one command for the entire stack):
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm upgrade --install kube-prometheus-stack \
prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=your-secure-password \
--wait
# Access Grafana
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
# Open http://localhost:3000 — login: admin / your-secure-password
This deploys Prometheus, Grafana, Alertmanager, Node Exporter, kube-state-metrics, and all required RBAC in a single command — replacing what would otherwise be hundreds of lines of individual YAML files.
Upgrade, Rollback, and Uninstall
# Show current release
helm list -n ingress-nginx
# REVISION 1
# Upgrade to a newer chart version
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--reuse-values \ # Keep existing values, only change what's specified
--version 4.12.0
# Check history
helm history ingress-nginx -n ingress-nginx
# REVISION STATUS CHART DESCRIPTION
# 1 superseded ingress-nginx-4.11.0 Install complete
# 2 deployed ingress-nginx-4.12.0 Upgrade complete
# Something broke — roll back to revision 1
helm rollback ingress-nginx 1 -n ingress-nginx
# Rollback was a success! Happy Helming!
helm history ingress-nginx -n ingress-nginx
# REVISION STATUS CHART DESCRIPTION
# 1 superseded ingress-nginx-4.11.0 Install complete
# 2 superseded ingress-nginx-4.12.0 Upgrade complete
# 3 deployed ingress-nginx-4.11.0 Rollback to 1
# Uninstall when done
helm uninstall ingress-nginx -n ingress-nginx
--atomic flag for production upgrades:
helm upgrade my-app bitnami/nginx \
--atomic \
--timeout 5m \
--cleanup-on-fail
--atomic makes the upgrade automatically roll back if it fails — the single best flag to add to all production upgrade commands. It turns a potentially broken cluster into a guaranteed-working-previous-version cluster.
Create Your First Helm Chart
The helm create command scaffolds a complete chart with best-practice templates.
# Create a new chart scaffold
helm create my-webapi
# View the generated structure
tree my-webapi
# my-webapi/
# ├── Chart.yaml ← Chart metadata (name, version, description)
# ├── values.yaml ← Default configuration values
# ├── charts/ ← Chart dependencies
# └── templates/
# ├── _helpers.tpl ← Template helper functions
# ├── deployment.yaml ← Deployment template
# ├── hpa.yaml ← HorizontalPodAutoscaler
# ├── ingress.yaml ← Ingress
# ├── NOTES.txt ← Post-install message
# ├── service.yaml ← Service
# ├── serviceaccount.yaml
# └── tests/
# └── test-connection.yaml
Chart.yaml — the chart’s identity:
apiVersion: v2
name: my-webapi
description: A Helm chart for My Web API
type: application
version: 0.1.0 # Chart version (increment on chart changes)
appVersion: "1.2.3" # Application version (tracks app releases)
maintainers:
- name: Ramansah
email: admin@bckinfo.com
values.yaml — default configuration:
replicaCount: 2
image:
repository: myregistry.com/my-webapi
pullPolicy: IfNotPresent
tag: "1.2.3"
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: "nginx"
hosts:
- host: api.yourdomain.com
paths:
- path: /
pathType: Prefix
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Test, lint, and render before installing:
# Lint: check for syntax errors and best practice violations
helm lint ./my-webapi
# ==> Linting ./my-webapi
# [INFO] Chart.yaml: icon is recommended
# 1 chart(s) linted, 0 chart(s) failed
# Render templates to stdout — verify generated YAML
helm template my-webapi-release ./my-webapi \
--set image.tag=1.3.0 \
--set ingress.hosts[0].host=api.staging.yourdomain.com
# Install from local chart
helm install my-webapi ./my-webapi -f values-production.yaml
# Package the chart for distribution
helm package ./my-webapi
# Successfully packaged chart and saved it to: my-webapi-0.1.0.tgz
OCI Registry Support
Helm 3 supports OCI registries, using the same infrastructure as container images. Instead of hosting a separate Helm repository, you can store charts alongside your container images in a standard container registry (Docker Hub, GitHub Container Registry, AWS ECR, etc.):
# Package your chart
helm package ./my-webapi
# Creates: my-webapi-0.1.0.tgz
# Push to GitHub Container Registry
helm push my-webapi-0.1.0.tgz oci://ghcr.io/myorg/charts
# Install directly from OCI registry
helm install my-release \
oci://ghcr.io/myorg/charts/my-webapi \
--version 0.1.0
# Pull to local without installing
helm pull oci://ghcr.io/myorg/charts/my-webapi --version 0.1.0
Practical benefit: OCI-based chart storage works with the same authentication (docker login) and access controls as your container images — no need to manage a separate Helm repository server.
The helm diff Plugin: Preview Before Upgrade
The helm diff plugin is the single best addition to your workflow after the basics — it turns upgrades from surprises into reviewed changes.
# Install the diff plugin
helm plugin install https://github.com/databus23/helm-diff
# Preview what an upgrade would change before applying it
helm diff upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--reuse-values \
--version 4.12.0
Output shows a git-diff-style preview:
ingress-nginx, ingress-nginx-controller, Deployment (apps) has changed:
# Source: ingress-nginx/templates/controller-deployment.yaml
...
- image: registry.k8s.io/ingress-nginx/controller:v1.11.0@sha256:...
+ image: registry.k8s.io/ingress-nginx/controller:v1.12.0@sha256:...
...
Review the diff, confirm only expected changes are present, then apply. This single habit catches most production upgrade surprises before they happen.
Helm in CI/CD Pipelines
Standard pattern for deploying to Kubernetes from GitLab CI or GitHub Actions:
# .gitlab-ci.yml — Helm deployment stage
deploy-production:
stage: deploy
image: alpine/helm:3.21.3 # Pin Helm version for reproducibility
script:
# Add and update repos
- helm repo add myorg oci://ghcr.io/myorg/charts
- helm repo update
# Deploy with --atomic for automatic rollback on failure
- helm upgrade --install my-webapi myorg/my-webapi
--namespace production
--create-namespace
--set image.tag=$CI_COMMIT_SHORT_SHA
--set ingress.hosts[0].host=api.yourdomain.com
--atomic
--timeout 5m
--cleanup-on-fail
--wait
environment:
name: production
url: https://api.yourdomain.com
only:
- main
Key CI/CD best practices:
- Always use
--atomic— automatic rollback on failure prevents a broken deployment from staying broken - Pin the Helm image version (
alpine/helm:3.21.3) — avoids unexpected behavior from automatic minor updates in CI - Use
$CI_COMMIT_SHORT_SHAas the image tag — every deployment is traceable to a specific commit - Use
--wait— the pipeline only succeeds when Kubernetes reports all resources ready, not just whenkubectl applyfinished
Helm 4.0: What’s Coming in September 2026
Helm 4.0 and 3.22.0 are the next minor releases scheduled for September 9, 2026.
Helm 4 will bring some breaking changes worth knowing about if you plan to upgrade:
- Removed
--reuse-valuesdefault — Helm 4 will require explicit values on every upgrade, reducing surprising “reuse of old values” bugs - Stricter schema validation — chart values will be more strictly validated against
values.schema.json - Library chart improvements — better support for shared helper templates across chart ecosystems
- Improved 3-way strategic merge — more accurate detection of out-of-band changes to managed resources
For current production deployments: stay on Helm 3.21.x until Helm 4.0 is released and tested by the community (typically 1-2 months post-release before enterprise adoption).
Common Issues and Quick Fixes
| Symptom | Likely Cause | Fix |
|---|---|---|
helm: command not found after APT install | PATH not updated | Run source ~/.bashrc or open a new terminal |
Error: INSTALLATION FAILED: cannot re-use a name | Release name already exists | Use helm upgrade --install instead of helm install |
Error: release has no deployed releases | Release in failed state | helm history <release> to check; helm rollback or helm uninstall then reinstall |
| Chart upgrade times out | Pods not becoming ready | Check kubectl get pods -n <namespace>; check resource limits and image pull status |
Error: repo already exists | Repository already added | Run helm repo update instead; or helm repo remove then re-add |
helm diff shows no output | No changes detected | Expected — upgrade would make no changes |
Error: rendered manifests contain a resource that already exists | Pre-existing resource not owned by Helm | Add --force flag or manually delete the conflicting resource |
| Snap Helm version lags behind | Snap update cycle slower than releases | Switch to APT or binary install method |
Reset a failed release:
# List all releases including failed ones
helm list -A --all
# Delete a failed release and start fresh
helm uninstall my-release -n my-namespace
# Or force delete
helm uninstall my-release -n my-namespace --no-hooks
Next Steps
With Helm installed and working on Ubuntu 26.04:
- Install an Ingress Controller — use Helm to deploy the NGINX Ingress Controller with a single command:
helm install ingress-nginx ingress-nginx/ingress-nginx. See our Deploy NGINX Ingress Controller guide for the full configuration. - Install MetalLB —
helm install metallb metallb/metallb— see our Install MetalLB on Bare Metal Kubernetes guide for the post-install IP pool configuration. - Deploy Prometheus + Grafana —
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack— see our Prometheus + Grafana Monitoring Stack guide for dashboard and alerting configuration. - Install KubeSphere —
helm install ks-core https://charts.kubesphere.io/main/ks-core-1.1.3.tgzfor a full web-based cluster management UI — see our KubeSphere and Kubernetes Security guide. - Learn chart development — the
helm createscaffold is the starting point; addvalues.schema.jsonfor input validation, write tests intemplates/tests/, and publish to an OCI registry for team sharing.







