A pragmatic GitOps setup with Argo CD
Skip the dogma. Here's a GitOps layout with Argo CD that small teams can actually run — app-of-apps, environments, and sane secrets.

GitOps gets sold as a philosophy. In practice it's a deployment workflow: your cluster state lives in Git, and a controller reconciles reality to match. Argo CD does the reconciling. Here's a layout that holds up past the demo.
Repo structure
Keep one repo for app source and a separate repo for delivery. The delivery repo is what Argo watches:
delivery/
apps/ # app-of-apps definitions
environments/
staging/
production/
base/ # shared kustomize bases
App of apps
Bootstrap a single root Application that points at apps/, and let it manage every other Application. One kubectl apply and the cluster wires itself up:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
spec:
source:
repoURL: https://github.com/acme/delivery
path: apps
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
Promotions are pull requests
Promoting staging → production is just a PR that bumps an image tag in environments/production. Reviewable, revertable, auditable.
- Auto-sync in staging so it tracks
main. - Manual sync (or a PR gate) in production.
selfHeal: trueso nobody fixes drift by hand.
Secrets, without tears
Don't put secrets in Git, even encrypted, if you can avoid it. Use the External Secrets Operator to pull from your cloud secret manager and let Argo manage the reference, not the value.
The goal isn't purity. It's that any engineer can answer "what's running in prod and why?" by reading one repo.
Start here, add Argo Rollouts for canaries when you actually need them, and resist the urge to template everything on day one.