Create a local Kubernetes cluster, install Argo CD, and deploy an application that continuously reconciles itself from Git. The tutorial includes a fast automated path and a step-by-step path that explains what each component does.
Git push -> Argo CD detects the revision -> Kustomize renders it -> Minikube is reconciled
Allow about 15–25 minutes for the first run, mostly for downloading images. No cloud account, DNS name, or ingress controller is required.
This is a learning environment. The non-HA installation, administrator login, broad namespace permissions inside the tutorial project, and local port forwarding are not a production configuration.
The central pins live in .versions.env. They were checked on
4 August 2026.
| Component | Tested version | Purpose |
|---|---|---|
| Kubernetes | v1.36.3 |
Local cluster API and workloads |
| Minikube | v1.38.1 |
Local cluster lifecycle |
| Argo CD | v3.5.0 |
GitOps controller, API, CLI, and UI |
| Kubeconform | v0.8.0 |
Optional local and CI schema validation |
Argo CD 3.5 is officially tested with Kubernetes 1.33 through 1.36, so the
latest versions used by this tutorial are within the published compatibility
matrix.
.
├── cluster/ # Pinned Argo CD installer
├── bootstrap/ # Restricted AppProject and main Application
├── advanced/ # Optional dev/staging ApplicationSet
├── examples/hello-app/
│ ├── base/ # Deployment, Service, and generated ConfigMap
│ └── overlays/ # local, dev, and staging Kustomize overlays
├── scripts/ # Safe setup, verification, and maintenance tools
├── docs/ # Concepts and optional learning tracks
└── Makefile # Short user-facing commands
The main Application enables automatic sync, pruning, self-healing, namespace
creation, and retry backoff. Its AppProject limits it to this repository and
namespaces matching hello-*.
You need Git, Make, kubectl, Minikube, the Argo CD CLI, and either Docker or
Podman. On macOS:
brew install git make kubectl minikube argocdInstall and start Docker Desktop if you do not already have a container engine. See platform setup for Linux, Windows/WSL, Apple Silicon, and Podman instructions.
Fork this repository so that you can push GitOps changes, then clone your fork:
git clone https://github.com/YOUR-USER/argocd.git
cd argocdThe automation derives the Argo CD source URL and branch from your origin
remote. You can override them at any time:
make bootstrap \
REPO_URL=https://github.com/YOUR-USER/argocd.git \
REVISION=mainArgo CD reads the remote repository—not uncommitted files on your computer.
Run the preflight check, create the cluster, install Argo CD, bootstrap the application, and execute the smoke test:
make doctor
make allmake all stops at the first failure and prints diagnostics. If it succeeds,
the Application is Synced, the workload is Healthy, two replicas are ready,
and an in-cluster HTTP request has returned the expected page.
Open the application in a separate terminal:
make port-forward-appVisit http://localhost:8081.
The sections below perform the same workflow one checkpoint at a time.
make doctorExpected checkpoint: every command is found and the selected container engine
is reachable. The default driver is Docker; use DRIVER=podman for Podman.
make clusterThe defaults are equivalent to:
minikube start \
--profile argocd \
--driver docker \
--container-runtime containerd \
--cpus 4 \
--memory 6144 \
--kubernetes-version v1.36.3Expected checkpoint:
NAME STATUS ROLES VERSION
argocd Ready control-plane v1.36.3
All scripts refuse to modify Kubernetes if the active context is not the configured Minikube profile. Override resources when necessary:
make cluster CPUS=3 MEMORY=4096 DRIVER=podmanmake installThis applies cluster/ with server-side apply, waits for the CRDs, and checks
all Argo CD Deployment and StatefulSet rollouts. Expected checkpoint: every pod
in the argocd namespace is Running and ready.
Inspect without changing the cluster:
kubectl get pods --namespace argocd
kubectl get crd applications.argoproj.ioKeep the UI port-forward running:
make port-forward-argocdVisit https://localhost:8080. A certificate warning is expected because this disposable environment uses a self-signed certificate.
In another terminal:
argocd admin initial-password --namespace argocd
argocd login localhost:8080 \
--username admin \
--password "$(argocd admin initial-password --namespace argocd | head -1)" \
--insecureEnsure the current revision is committed and pushed, then run:
make bootstrap
make verifyThe bootstrap command applies the local resources with reconciliation paused, sets your detected Git remote and branch, and then enables reconciliation. It does not generate or render an intermediate manifest. It creates:
local-tutorial, an AppProject restricted to the repository andhello-*;hello-minikube, an Application watchingoverlays/local; and- the
hello-minikubenamespace and application resources through Argo CD.
Expected checkpoint:
NAME SYNC STATUS HEALTH STATUS
hello-minikube Synced Healthy
Use an explicit source when working from a different remote or branch:
make bootstrap REPO_URL=https://github.com/USER/REPO.git REVISION=feature/tutorialPrivate repositories require credentials before bootstrapping. Follow the private repository guide.
make port-forward-appVisit http://localhost:8081, or run:
curl http://localhost:8081
make statusEdit examples/hello-app/base/content/index.html, then render, commit, and push:
kubectl kustomize examples/hello-app/overlays/local
git add examples/hello-app/base/content/index.html
git commit -m "Change the tutorial page"
git push origin HEADKustomize gives the generated ConfigMap a content hash. The changed name updates the Deployment pod template, producing a real rolling update instead of waiting for a mounted ConfigMap cache refresh.
argocd app get hello-minikube --refresh
kubectl rollout status deployment/hello-minikube \
--namespace hello-minikube
kubectl get configmaps --namespace hello-minikubeCreate live drift without changing Git:
kubectl scale deployment hello-minikube \
--namespace hello-minikube \
--replicas 1
kubectl get deployment hello-minikube \
--namespace hello-minikube \
--watchArgo CD restores the two replicas declared by overlays/local. Press Ctrl+C
after the replica count returns to two.
Delete base/prune-demo.yaml and remove it from base/kustomization.yaml, then
commit and push:
git add examples/hello-app/base
git commit -m "Remove the prune demonstration resource"
git push origin HEAD
argocd app get hello-minikube --refreshObserve Argo CD remove the ConfigMap because prune: true:
kubectl get configmap prune-demo --namespace hello-minikubeExpected result: NotFound.
Restore the previous desired state with Git rather than editing the cluster:
git revert HEAD
git push origin HEAD
argocd app get hello-minikube --refresh
make verifyArgo CD recreates prune-demo. This is the auditable GitOps rollback pattern.
- Core concepts and security boundaries
- Kustomize overlays, ApplicationSet, and webhooks
- Private repository authentication
- Safe Argo CD upgrades and rollback
- Troubleshooting decision guide
- Platform-specific installation
make help # List commands and configurable variables
make status # Show cluster, controllers, and application
make verify # Repeat the complete smoke test
make render # Render every Kustomization locally
make validate # Schema-check manifests and lint scripts/docs
make check-versions # Compare pins with upstream stable releases
make stop # Preserve but stop the cluster
make start # Restart the same profile
make upgrade # Preview and apply a pinned Argo CD upgrade
make clean # Confirm and delete only this Minikube profileFor complete local validation on macOS, install the development tools once:
brew install kubeconform shellcheck node
npm install --global markdownlint-cli2@0.18.1
make validateDelete only the example and wait for its finalizer to prune managed resources before deleting the project:
kubectl delete application hello-minikube --namespace argocd
kubectl wait --for=delete application/hello-minikube \
--namespace argocd \
--timeout=300s
kubectl delete appproject local-tutorial --namespace argocdDelete the entire disposable cluster with an interactive profile-name check:
make cleanGit files remain unchanged, so the environment can be recreated with
make all.
GitHub Actions renders and schema-validates every manifest, lints Bash and
Markdown, checks documentation links, and performs a weekly version check.
Dependabot updates GitHub Actions. The included renovate.json5 updates tool
pins, the Argo CD manifest, and the digest-pinned NGINX image when the Renovate
app is enabled for the repository.
Primary references: