DevOps & Platform

Setting Up ArgoCD with Automated Sync and Rollback

Intermediate50 min to complete12 min read

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.

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 git@github.com: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 set as the ARGOCD_WEBHOOK_SECRET environment variable in argocd-server
  • 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 --sync --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):

bash
argocd app rollback my-app 0

This deploys revision 0 without changing Git. ArgoCD will show the app as OutOfSync because the cluster no longer matches the repo HEAD. Fix by doing a proper Git revert and re-syncing.

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 --sync-policy none and requires manual 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/managed-by: argocd labels to adopt resources.

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

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.