ArgoCD managing itself is peak GitOps
Make ArgoCD deploy its own updates. Yes, it can delete and recreate itself. No, it does not explode.
You install ArgoCD with Helm. You use ArgoCD to deploy everything else. But who deploys ArgoCD?
You do. Manually. Like a peasant
There’s a better way. Make ArgoCD manage itself. Push a change to your ArgoCD Helm values, and ArgoCD picks it up, diffs it, and upgrades itself. Full GitOps. No kubectl apply. No Helm upgrade commands
The existential question
Can ArgoCD delete and recreate its own pods while processing a sync? What happens when the controller pod restarts mid-reconciliation?
Turns out: nothing bad. ArgoCD is designed for this. The sync state is stored in Kubernetes resources, not in memory. When pods restart, they pick up where they left off. I’ve watched ArgoCD kill its own controller pod and come back 10 seconds later to finish the sync
It’s like a surgeon operating on themselves, except it actually works
The setup
Create an Application that points to ArgoCD itself:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd
namespace: argocd
spec:
project: default
source:
repoURL: https://argoproj.github.io/argo-helm
chart: argo-cd
targetRevision: 7.7.5
helm:
valuesObject:
configs:
params:
server.insecure: false
server:
replicas: 2
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true That’s it. ArgoCD now watches its own Helm chart. Change the version, change a value, push to git. ArgoCD syncs itself
The chicken and egg
How do you create this Application if ArgoCD doesn’t exist yet?
Option 1: Install ArgoCD first with Helm, then create the Application. ArgoCD adopts itself
helm install argocd argo/argo-cd -n argocd
kubectl apply -f argocd-application.yaml Option 2: Use the App of Apps pattern. Your bootstrap Application creates all other Applications, including the one for ArgoCD
Option 3: Include the Application in the Helm chart itself using server.additionalApplications
I use option 1. It’s simple. The manual install happens once. After that, everything is GitOps
What happens during self-upgrade
- You push new values to git
- ArgoCD detects drift
- ArgoCD starts syncing
- Helm upgrade runs, pods get replaced
- ArgoCD controller restarts
- New controller comes up, checks sync status
- Sync completes (or retries if interrupted)
The key: selfHeal: true means if something breaks mid-sync, ArgoCD will retry until it matches the desired state
The fun part
Watch the UI while ArgoCD upgrades itself. You’ll see the pods go yellow (progressing), then the UI disconnects for a few seconds, then it comes back and everything is green
It’s weirdly satisfying. Like watching a robot fix itself
Handling CRDs
ArgoCD CRDs need special attention. If you upgrade CRDs through the Application, make sure the CRDs are applied before the controller tries to use them
The Helm chart handles this with a pre-install hook. But if you’re paranoid, you can manage CRDs separately with a dedicated Application that syncs first:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd-crds
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "-1"
spec:
source:
repoURL: https://github.com/argoproj/argo-cd
path: manifests/crds
targetRevision: v2.13.0
destination:
server: https://kubernetes.default.svc
namespace: argocd Sync wave -1 means CRDs deploy before the main ArgoCD Application
When it goes wrong
I’ve had exactly one issue: a bad config that made ArgoCD crash loop. It couldn’t sync because it couldn’t start. Classic deadlock
The fix: kubectl apply the previous working version manually. Once ArgoCD is healthy, it syncs back to git (which you’ve fixed by then)
This is why you want replicas: 2 for the controller. If one pod crashes during upgrade, the other keeps things running
The meta gets deeper
You can go further. ArgoCD managing ArgoCD managing your apps. ArgoCD Image Updater watching for new ArgoCD versions and creating PRs. Renovate bumping the chart version automatically
At some point you’re just watching robots update robots. And that’s the goal. You push code, everything else happens automatically
Should you do this?
Yes. If you’re using ArgoCD for everything else, not using it for ArgoCD itself is inconsistent. You lose the audit trail. You lose the drift detection. You’re back to “I think I ran helm upgrade last month”
The self-management works. ArgoCD handles it gracefully. And there’s something philosophically satisfying about a tool that practices what it preaches
Enjoyed this article? Share it!


