Part ofGitOps with ArgoCD·Step 3 of 4
DevOps & Platform

Setting Up ArgoCD with Automated Sync and Rollback

Intermediate50 min to complete12 min readApril 22, 2026Updated August 19, 2026

Quick answer

Install ArgoCD on Kubernetes, connect your Git repository, and configure automated sync so every push to main deploys automatically — with one-command rollback when something goes wrong.

intermediate · 50 min

Before you begin

  • A running Kubernetes cluster
  • kubectl configured with admin access
  • Helm 3 installed
  • A Git repository containing Kubernetes manifests or Helm charts
ArgoCD
GitOps
Kubernetes
CI/CD
DevOps

ArgoCD is a GitOps controller that makes your Git repository the source of truth for Kubernetes. Instead of running kubectl apply in a CI pipeline, ArgoCD watches your repo and reconciles the cluster state continuously. Drift gets corrected automatically. Rollback means reverting a Git commit.

This tutorial installs ArgoCD, creates your first Application, enables automated sync, and shows you how rollback actually works.

Step 1: Install ArgoCD

bash
kubectl create namespace argocd

kubectl apply -n argocd -f \
  https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Wait for all pods to be ready:

bash
kubectl wait --for=condition=Ready pods --all -n argocd --timeout=120s
kubectl get pods -n argocd

Expected output — all pods Running:

NAME                                  READY   STATUS
argocd-application-controller-0       1/1     Running
argocd-dex-server-xxx                 1/1     Running
argocd-notifications-controller-xxx   1/1     Running
argocd-redis-xxx                      1/1     Running
argocd-repo-server-xxx                1/1     Running
argocd-server-xxx                     1/1     Running

Step 2: Access the ArgoCD UI

By default, the argocd-server is exposed as ClusterIP. Forward the port locally:

bash
kubectl port-forward svc/argocd-server -n argocd 8080:443

Open https://localhost:8080 (accept the self-signed cert warning).

Get the initial admin password:

bash
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d && echo

Log in with username admin and the password above. Change it immediately:

bash
# Install the argocd CLI
brew install argocd   # macOS; see https://argo-cd.readthedocs.io for other platforms

argocd login localhost:8080 --insecure --username admin
argocd account update-password

Step 3: Connect Your Git Repository

If your repo is public, skip this step — ArgoCD reads public repos without credentials.

For a private repo:

bash
argocd repo add https://github.com/your-org/your-repo \
  --username your-github-username \
  --password your-github-pat

For SSH:

bash
argocd repo add [email protected]:your-org/your-repo.git \
  --ssh-private-key-path ~/.ssh/id_ed25519

Verify:

bash
argocd repo list

Step 4: Create an Application with Automated Sync

An ArgoCD Application defines what to deploy (source) and where (destination).

bash
1argocd app create my-app \
2  --repo https://github.com/your-org/your-repo \
3  --path k8s/overlays/production \
4  --dest-server https://kubernetes.default.svc \
5  --dest-namespace production \
6  --sync-policy automated \
7  --auto-prune \
8  --self-heal

What each flag does:

  • --path k8s/overlays/production — directory inside the repo containing your manifests
  • --dest-server https://kubernetes.default.svc — deploy to the same cluster ArgoCD runs in
  • --sync-policy automated — sync whenever the repo changes (polling every 3 minutes, or on webhook push)
  • --auto-prune — delete Kubernetes resources when they're removed from Git
  • --self-heal — revert manual kubectl apply changes that drift from Git

Or declaratively via a YAML manifest (preferred for production):

yaml
1# argocd-app.yaml
2apiVersion: argoproj.io/v1alpha1
3kind: Application
4metadata:
5  name: my-app
6  namespace: argocd
7spec:
8  project: default
9  source:
10    repoURL: https://github.com/your-org/your-repo
11    targetRevision: main
12    path: k8s/overlays/production
13  destination:
14    server: https://kubernetes.default.svc
15    namespace: production
16  syncPolicy:
17    automated:
18      prune: true
19      selfHeal: true
20    syncOptions:
21      - CreateNamespace=true
22    retry:
23      limit: 3
24      backoff:
25        duration: 5s
26        factor: 2
27        maxDuration: 3m
bash
kubectl apply -f argocd-app.yaml

Step 5: Configure a Webhook for Instant Sync

By default, ArgoCD polls Git every 3 minutes. Configure a webhook for immediate sync on push.

In your GitHub repo → Settings → Webhooks → Add webhook:

  • Payload URL: https://your-argocd-domain/api/webhook
  • Content type: application/json
  • Secret: generate with openssl rand -hex 32 and store it with the kubectl patch command below
  • Events: Just the push event

Or generate a shared secret and store it:

bash
kubectl -n argocd patch secret argocd-secret \
  --type='merge' \
  -p='{"stringData":{"webhook.github.secret":"your-webhook-secret"}}'

Step 6: Verify Sync Status

After committing a change to your repo:

bash
1# Check sync status
2argocd app get my-app
3
4# Watch it sync
5argocd app wait my-app --health
6
7# See what changed
8argocd app diff my-app

The UI (localhost:8080) shows a visual dependency graph — green circles are healthy, yellow is progressing, red means something's wrong.

Step 7: Rollback to a Previous Version

When a deployment goes bad, rollback is a Git revert followed by a push. ArgoCD handles the rest.

bash
# See sync history
argocd app history my-app

# ID  DATE                           REVISION
# 0   2026-04-22 10:00:00 +0000 UTC  main (abc1234)
# 1   2026-04-22 11:00:00 +0000 UTC  main (def5678)  ← broken deploy

Option 1: Git revert (preferred — keeps history):

bash
git revert HEAD --no-edit
git push origin main
# ArgoCD auto-syncs to the reverted state

Option 2: ArgoCD rollback to a specific history entry (bypasses Git — use only in emergencies):

Note: argocd app rollback cannot be used while automated sync is enabled — ArgoCD will refuse the command. Disable automated sync first, then roll back:

bash
argocd app set my-app --sync-policy none
argocd app rollback my-app 0

This deploys revision 0 without changing Git. After the emergency is resolved, re-enable automated sync:

bash
argocd app set my-app --sync-policy automated --auto-prune --self-heal

ArgoCD will show the app as OutOfSync until the next auto-sync runs.

Step 8: Application Health Checks

ArgoCD understands Kubernetes resource health natively. A Deployment is Healthy when its rollout is complete. A Pod is Degraded when it's in CrashLoopBackOff.

For custom health checks, add a ConfigMap to argocd-cm:

yaml
1apiVersion: v1
2kind: ConfigMap
3metadata:
4  name: argocd-cm
5  namespace: argocd
6data:
7  resource.customizations.health.my.io_MyResource: |
8    hs = {}
9    if obj.status ~= nil then
10      if obj.status.phase == "Ready" then
11        hs.status = "Healthy"
12        hs.message = "Resource is ready"
13        return hs
14      end
15    end
16    hs.status = "Progressing"
17    hs.message = "Waiting for resource to be ready"
18    return hs

Step 9: Multi-Environment Setup

For separate dev, staging, and production apps pointing to the same repo but different paths:

bash
1argocd app create my-app-dev \
2  --repo https://github.com/your-org/your-repo \
3  --path k8s/overlays/dev \
4  --dest-server https://kubernetes.default.svc \
5  --dest-namespace dev \
6  --sync-policy automated \
7  --auto-prune \
8  --self-heal
9
10argocd app create my-app-staging \
11  --repo https://github.com/your-org/your-repo \
12  --path k8s/overlays/staging \
13  --dest-server https://kubernetes.default.svc \
14  --dest-namespace staging \
15  --sync-policy automated \
16  --auto-prune \
17  --self-heal

Production typically has no --sync-policy flag (manual sync only) and requires explicit approval via the UI or argocd app sync my-app-prod.

Common Issues

App stuck in OutOfSync: Run argocd app diff my-app to see what's different. Often caused by resources that get mutated by admission webhooks (like injected sidecars or annotations). Use ignoreDifferences in the Application spec to ignore these fields.

Sync loop with self-heal: If the cluster keeps drifting back to a different state, something outside ArgoCD is modifying resources. Find the culprit with kubectl get events -n production.

Prune deletes unexpected resources: ArgoCD prunes resources it created but are no longer in Git. If you deployed something manually with kubectl apply, ArgoCD doesn't own it and won't prune it. Add app.kubernetes.io/instance: my-app labels to adopt resources into the ArgoCD application.

Frequently Asked Questions

What is the difference between automated sync and self-heal?

Automated sync applies changes when the Git repository moves ahead. Self-heal additionally reverts changes made directly in the cluster, so a manual kubectl edit is undone at the next reconcile. Enable self-heal when Git must be the only source of truth; leave it off if operators legitimately patch resources by hand during incidents.

Why does my application show OutOfSync when nothing changed?

Usually a controller or admission webhook mutating the resource after it is applied — an injected sidecar, a defaulted field, or a mutating policy. Argo CD compares the live object against Git and reports the difference honestly. Use ignoreDifferences for fields you expect something else to own, rather than disabling the comparison.

Do I need a webhook, or is polling enough?

Polling works and defaults to a few minutes, which is fine for most teams. A webhook makes sync near-instant, which matters when deploys are frequent enough that waiting is noticeable. The webhook is an optimisation, not a requirement, and polling remains the fallback if it fails.

How does rollback work if Git is the source of truth?

Argo CD blocks rollback entirely while automated sync is enabled — the operation is rejected, because the controller would immediately re-sync to Git anyway. The durable rollback is therefore a Git revert, which is also auditable. If you must roll back from the UI during an incident, disable automated sync first, roll back, then revert in Git and re-enable it.

Official References

  • Argo CD Documentation — Official docs: installation, Applications, sync policies, RBAC, SSO, and notifications
  • Argo CD Application Spec — Full reference for the Application CRD including syncPolicy, retry, and prune settings
  • Automated Sync Policy — Official guide to automated sync, self-heal, and prune behaviour
  • Argo CD Notifications — How to send Slack/email/webhook alerts on sync success, failure, or health changes
  • App of Apps Pattern — Managing multiple Applications with a parent Application for cluster bootstrapping

Next in GitOps with ArgoCD

ArgoCD App-of-Apps: Managing Multi-Environment Clusters

Continue

We built Podscape to simplify Kubernetes workflows like this — logs, events, and cluster state in one interface, without switching tools.

Struggling with this in production?

We help teams fix these exact issues. Our engineers have deployed these patterns across production environments at scale.