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
argocd app create my-app \
  --repo https://github.com/your-org/your-repo \
  --path k8s/overlays/production \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace production \
  --sync-policy automated \
  --auto-prune \
  --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
# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/your-repo
    targetRevision: main
    path: k8s/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
    retry:
      limit: 3
      backoff:
        duration: 5s
        factor: 2
        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
# Check sync status
argocd app get my-app

# Watch it sync
argocd app wait my-app --sync --health

# See what changed
argocd 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
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations.health.my.io_MyResource: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.phase == "Ready" then
        hs.status = "Healthy"
        hs.message = "Resource is ready"
        return hs
      end
    end
    hs.status = "Progressing"
    hs.message = "Waiting for resource to be ready"
    return hs

Step 9: Multi-Environment Setup

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

bash
argocd app create my-app-dev \
  --repo https://github.com/your-org/your-repo \
  --path k8s/overlays/dev \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace dev \
  --sync-policy automated \
  --auto-prune \
  --self-heal

argocd app create my-app-staging \
  --repo https://github.com/your-org/your-repo \
  --path k8s/overlays/staging \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace staging \
  --sync-policy automated \
  --auto-prune \
  --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.

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.