← Back to blog

Helm with Argo CD: Deploy Charts the GitOps Way

October 29, 2026
Helm with Argo CD: Deploy Charts the GitOps Way

Helm packages and templates your Kubernetes manifests. Argo CD watches a source, renders it and keeps the cluster matching it. Used together, you describe a chart, a version and a set of values in an Argo CD Application, and Argo CD does the rendering, applying and drift detection. The catch is that Argo CD does not run helm install, so a few Helm habits stop working. This guide covers how the pairing works, how to write the Application, how to handle values and environments, and what to check when something looks wrong.

Kubezilla Desktop
kubezilladesktop.com
Manage Helm and Argo CD Together
Kubezilla Desktop brings Helm and ArgoCD operations, live logs, and cluster metrics into one interface for managing Kubernetes environments.
Explore Kubezilla Desktop

TL;DR

  • Argo CD renders charts with helm template and applies the output itself. The app is tracked as an Argo CD Application, not as a Helm release.
  • Point spec.source at a Helm repository, an OCI registry or a Git path, pin the chart version in targetRevision, and set values with valuesObject, valueFiles or parameters.
  • For several environments, keep one chart and one values file per environment in Git, and generate Applications with an ApplicationSet or App of Apps.
  • Expect helm ls to come back empty, Helm hooks to be mapped onto Argo CD hooks, and private chart repositories to need registering first.

Table of Contents

How Helm and Argo CD fit together

The two tools do different jobs. Helm is the packaging and templating layer: a chart plus values produces manifests. Argo CD is the GitOps controller: it compares what is declared with what runs and reconciles the difference. Argo CD's Helm documentation states it plainly: Argo CD uses Helm to inflate charts with helm template, and Argo CD handles the application's lifecycle.

That design has practical consequences:

  • No Helm release object. The chart is turned into raw manifests that Argo CD applies, so the application is tracked as an Argo CD resource rather than a standard Helm release. Red Hat's write-up on Helm and Argo CD notes the visible effect: helm ls will not list charts that Argo CD manages.
  • Git is the control point. Chart version, values and target namespace live in a manifest you can review and revert.
  • Drift is visible. Argo CD keeps comparing the live state with the rendered desired state, and with automated sync it can correct differences.

If you come from helm upgrade --install in a pipeline, the mental shift is this: you no longer push a release. You change a declaration and let the controller converge.

Three ways to source a chart

Argo CD can read Helm charts from three kinds of places. Red Hat's overview of three patterns describes the split: a chart in a Git repository (URL and path), or a chart from a remote Helm repository (chart name, repository URL and target revision).

SourceWhat you set in spec.sourceBest for
Helm repositoryrepoURL, chart, targetRevisionThird-party charts such as ingress controllers or monitoring stacks
OCI registryrepoURL (no oci:// prefix), chart, targetRevisionCharts your team publishes to a container registry
Git repositoryrepoURL, path, targetRevision (branch, tag or commit)Charts you own and change alongside the app

For public OCI registries, the Argo CD docs say to give the repository URL without the oci:// prefix. A Git-hosted chart is the simplest way to start: the chart and its values move through the same pull request.

Writing the Application manifest

An Application can be created in the UI, with the CLI, or by applying YAML. The YAML is the one worth keeping, because you can commit it. Here is an Application that installs a chart from a Helm repository:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ingress-nginx
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://kubernetes.github.io/ingress-nginx
    chart: ingress-nginx
    targetRevision: 4.11.3
    helm:
      releaseName: ingress-nginx
      valuesObject:
        controller:
          replicaCount: 2
  destination:
    server: https://kubernetes.default.svc
    namespace: ingress-nginx
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

The version number above is only an example of the format. Pick the chart version you have tested.

A few points about this manifest:

  • targetRevision holds the chart version for Helm and OCI sources. Pin an exact version. A floating range means a chart upstream can change what lands in production without a commit on your side.
  • destination.server is the cluster the resources go to. The in-cluster address means the cluster Argo CD itself runs in. For remote clusters you register them with Argo CD first.
  • automated with prune and selfHeal turns on the drift correction. Leave automated out while you are learning and sync manually.
  • releaseName matters because templates often use .Release.Name. Set it deliberately and do not change it later, or resource names change with it.

After you create the Application, expect it to show OutOfSync at first. After a sync, it moves to Synced and Healthy, as KodeKloud's walkthrough shows. To see exactly what Helm produced, open the app in the UI and check App Details, then Manifests.

Values, parameters and precedence

The values you give a chart can arrive in several ways, and the Argo CD docs define a strict order of precedence among them. The main inputs:

  • valueFiles: paths to values files in the source repository. Good for per-environment files.
  • valuesObject: values written inline as YAML in the Application. Convenient for a few overrides, harder to read when it grows.
  • parameters: single --set style overrides. On the CLI the equivalent is the --helm-set flag when you create the Application.

A workable rule: keep everything environment-wide in valueFiles, and use parameters only for values a pipeline needs to inject, such as an image tag. Mixing all three for the same key makes it hard to tell where a value came from. When in doubt, check the rendered manifest in the UI rather than guessing which input won.

Argo CD also supports value hierarchies, where several files layer from general to specific. Its multi-source feature lets you keep the chart in one repository and the values in another, which suits third-party charts. Akuity's guide to Helm hierarchies in multi-source Applications walks through that layout, including ApplicationSets.

Managing several environments

Once one Application works, the question becomes how to avoid copying it for dev, staging and production. Two patterns cover most teams.

One chart, one values file per environment

Keep a single chart and a folder of values files:

my-app/
  chart/
  values/
    dev.yaml
    staging.yaml
    prod.yaml

Each environment's Application points at the same chart and a different valueFiles entry. Because chart versions are set in targetRevision, dev can run a newer chart than prod and you promote by changing one line. Red Hat's patterns article describes this same idea of environment-specific charts or versions in Git.

ApplicationSet or App of Apps

Writing a dozen near-identical Applications by hand is where mistakes creep in. Two ways to avoid it:

  • ApplicationSet generates Applications from a template plus a list, a directory layout or a cluster list. One template, many environments or clusters.
  • App of Apps is a parent Application whose source is a folder of Application manifests. Declarative manifests stored in Git let Argo CD manage its own application definitions, as the Argo CD application creation guide describes.

A useful split: ApplicationSets for repeated shapes (the same app on many clusters), App of Apps for bootstrapping a cluster with a hand-curated set of platform components.

If your environments are separate clusters, you also need a safe way to give Argo CD access to them. We wrote about that in Argo CD across clusters without static tokens.

Sync behavior: updates, rollbacks and drift

When a chart version or its parameters change in the source, Argo CD detects the change and can redeploy it according to the sync policy, as Octopus Deploy's explainer puts it. With manual sync, the Application shows OutOfSync and waits for you. With automated sync, it applies the change.

Some habits that keep this calm:

  1. Review the diff before syncing. The diff shows rendered manifests, not chart values, so it catches template changes you did not expect when bumping a chart version.
  2. Treat Git as the rollback source. Argo CD supports rollback in the UI and CLI, but with automated sync a rollback in the UI can be undone by the next reconcile. Reverting the commit is the durable fix.
  3. Do not edit live resources. With selfHeal on, manual kubectl edit changes are reverted. With it off, they show as drift. Either way, the change belongs in Git.

Helm hooks and Argo CD hooks

Helm hooks are normal resources annotated with helm.sh/hook. Because Argo CD never runs helm install or helm upgrade, it handles them differently: the Argo CD Helm guide says it supports many Helm hooks by mapping the annotations onto its own hook annotations. It also warns that this is annotation compatibility, not a guarantee that lifecycle behavior is identical.

In practice:

  • Install and upgrade hooks both map to the same sync phase, because Argo CD does not tell a first install apart from a later sync the way Helm does.
  • A database migration Job that ran as a pre-upgrade hook will run before every sync, so make it idempotent.
  • For ordering regular resources, use Argo CD sync waves rather than relying on hook weights. For anything critical, test the chart in a non-production Application before trusting the mapping.

Private repositories and common problems

Most failed first deployments come from a short list of causes.

The repository is not registered. Private Helm and OCI repositories must be registered in Argo CD's settings before an Application can pull from them. Octopus Deploy's tutorial makes the same point for restricted environments. Argo CD's private repositories documentation shows both the CLI route (argocd repo add with --type helm and --enable-oci for OCI) and a declarative Secret labeled argocd.argoproj.io/secret-type: repository. The declarative Secret is the better choice if you want the setup reproducible.

helm ls shows nothing. This is expected, as covered above. Use kubectl or the Argo CD UI to see what is deployed, and look at the Application's resource tree.

The Application is OutOfSync forever. Usually a controller or webhook mutates a field that the chart also sets. Look at the diff for the field in question, then use ignoreDifferences for that specific path instead of disabling sync.

Values do not seem to apply. Check the rendered manifests in the UI, then check which of valueFiles, valuesObject and parameters sets the key.

Security. Pin chart versions, keep credentials in Secrets rather than in values files committed to Git, and scope each Application to an Argo CD Project that limits which repositories and namespaces it may touch. Review upstream chart changes in the rendered diff before bumping a version, since a chart is code that creates cluster resources.

Private repositories and common problems — overview diagram

Perspective: what we see in the day-to-day

Argo CD is excellent at declaring and reconciling. It is less comfortable when you need to look at what is happening right now: which pod is crash-looping, what its logs say, whether the new ReplicaSet ever became ready. The UI can show that, but teams that run many clusters end up juggling Argo CD tabs, kubectl contexts and a separate Helm client.

We build Kubezilla Desktop around that gap. Git and Argo CD stay the source of truth for what should run. A native desktop app is where you go to inspect, tail logs and open a pod terminal across clusters, with kubeconfigs stored locally, no cloud sync and no telemetry. Our rule of thumb for Helm with Argo CD is simple: change things in Git, observe them everywhere else, and keep the number of places you need credentials for as small as you can.

— Margus

Watching Helm and Argo CD work from one window

Kubezilla Desktop is a native app for Linux, macOS and Windows, built in Rust to stay light on RAM and fast to start. It gives you a single interface for your clusters, with live log streaming, metrics, pod terminals, YAML editing and workload scaling, plus Helm and Argo CD operations when you need them. It connects to multiple clusters, including remote ones through SSH tunnels, so you can skip VPN and bastion juggling. It costs €5 per month, and you can see the details on the Kubezilla Desktop pricing page.

Kubezilla Desktop

If you manage more than one cluster, see how the Kubernetes desktop app fits next to your GitOps setup. Two related guides: kubeconfig context management for keeping contexts straight, and Kubernetes dry runs for checking a change before it lands.

A short checklist before your first production sync

  1. Pin targetRevision to an exact chart version you have tested.
  2. Put values in files in Git, one per environment, and use parameters only for injected values like image tags.
  3. Register private repositories declaratively.
  4. Start with manual sync; turn on automated with prune and selfHeal once the diff is clean for a few syncs.
  5. Review the rendered Manifests view after every chart version bump.
  6. Make hook Jobs idempotent, and test hook behavior in a non-production Application.
  7. Assign each Application to a Project with restricted sources and destinations.

FAQ

Does Argo CD use Helm to install charts?

Only for rendering. Argo CD runs helm template to produce manifests and then applies them itself, so no Helm release is created. Lifecycle, sync and rollback are handled by Argo CD.

Why doesn't helm ls show my Argo CD application?

Because the chart was never installed as a Helm release. Argo CD tracks it as an Application resource instead. Use the Argo CD UI, the argocd app commands or kubectl to see what is deployed.

Where do I set the chart version?

In spec.source.targetRevision of the Application. For a Git source it is a branch, tag or commit instead. Pin an exact chart version for production so upgrades are always a reviewed commit.

How do I override Helm values in Argo CD?

Use valueFiles for files in the repository, valuesObject for inline YAML, or parameters for single overrides. From the CLI, the --helm-set flag does the latter when creating an Application. Check the rendered manifests in the UI to confirm what was applied.

Can I use a private chart repository?

Yes. Register the repository in Argo CD first, either with argocd repo add or with a declarative Secret, and add credentials there. Then reference it from the Application's repoURL.

Sources