Goal: Spin up a production-like GitOps environment entirely on your laptop using WSL2, Kind, and ArgoCD.
Stack: Docker · kubectl · Kind · Terraform · AWS CLI · ArgoCD · NGINX Ingress · Prometheus · Grafana · Loki · Promtail
DevOps-Bootstrap/
├── devops-bootstrap.sh ← Install all CLI tools in one shot
├── Kind-Cluster-Setup/
│ └── kind-config.yaml ← Kind cluster definition (1 control-plane + 2 workers)
├── GitOps-Argocd-Setup/
│ ├── argocd-install.sh ← Interactive: install / upgrade / delete ArgoCD
│ ├── argocd-ingress.yaml ← Exposes ArgoCD UI at /argocd via NGINX
│ ├── argocd-diag.sh ← Quick diagnostics (pods, ingress, logs)
│ └── gitops-agent.yaml ← Harness GitOps agent manifest (optional)
└── Applications/
├── tic-tac-toe/ ← Example containerised web app
│ ├── Dockerfile
│ ├── index.html
│ ├── argocd-manifest.yaml ← ArgoCD Application CR
│ ├── tic-tac-toe-manifests.yaml
│ └── manifest/
│ └── config.yaml ← Namespace + Deployment + Service + Ingress
└── monitoring/ ← Full observability stack
├── README.md ← Monitoring-specific docs
├── prometheus/
│ └── argocd-manifest.yaml
├── grafana/
│ └── argocd-manifest.yaml
├── loki/
│ └── argocd-manifest.yaml
└── promtail/
└── argocd-manifest.yaml
Run these steps in order on a fresh WSL2 / Ubuntu environment.
chmod +x devops-bootstrap.sh
./devops-bootstrap.shInstalls: Docker, kubectl, Kind, Terraform, AWS CLI v2, ArgoCD CLI — and adds bash completions for each.
After first-time Docker install, log out and back in so group membership takes effect.
kind create cluster --config Kind-Cluster-Setup/kind-config.yaml| Property | Value |
|---|---|
| Cluster name | devops |
| Topology | 1 control-plane + 2 workers |
| HTTP host port | 8080 → container port 80 |
| HTTPS host port | 8443 → container port 443 |
| kubeconfig context | kind-devops |
Verify:
kubectl cluster-info --context kind-devops
kubectl get nodeskubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
# Wait until ready
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90scd GitOps-Argocd-Setup
chmod +x argocd-install.sh
./argocd-install.sh
# Select option 1 (Install)The script:
- Creates the
argocdnamespace - Applies the official ArgoCD install manifest (version of your choice)
- Patches
argocd-serverto run--insecurewithrootpath=/argocd - Applies
argocd-ingress.yamlto expose the UI at/argocd - Prints admin credentials and logs in via CLI
Access the UI:
http://localhost:8080/argocd
| Credential | Value |
|---|---|
| Username | admin |
| Password | printed by script, or run: kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 -d && echo |
Change the default password after first login:
argocd account update-password
Browser → localhost:8080/<path>
↓
Kind extraPortMapping (hostPort 8080 → containerPort 80)
↓
NGINX Ingress Controller (ingress-nginx namespace)
↓
Path-based routing:
/argocd → argocd-server (no rewrite; ArgoCD handles rootpath itself)
/tic-tac-toe → tic-tac-toe (rewrite-target strips prefix)
/prometheus → prometheus (no rewrite; routePrefix set in Prometheus config)
/grafana → grafana (no rewrite; serve_from_sub_path in Grafana config)
All services speak plain HTTP — no NodePort or kubectl port-forward required.
kubectl apply -f Applications/tic-tac-toe/argocd-manifest.yamlArgoCD syncs from GitHub (techwhisper-in/tic-tac-toe) and deploys:
| Resource | Detail |
|---|---|
| Namespace | ns-tic-tac-toe |
| Image | techwhisper/ankit-public:tic-tac-toe_v0.0.1 |
| Replicas | 1 (RollingUpdate) |
| URL | http://localhost:8080/tic-tac-toe |
kubectl apply -f Applications/monitoring/prometheus/argocd-manifest.yaml
kubectl apply -f Applications/monitoring/grafana/argocd-manifest.yaml
kubectl apply -f Applications/monitoring/loki/argocd-manifest.yaml
kubectl apply -f Applications/monitoring/promtail/argocd-manifest.yaml| Service | URL | Credentials |
|---|---|---|
| Grafana | http://localhost:8080/grafana |
admin / admin123 |
| Prometheus | http://localhost:8080/prometheus |
— |
| Loki | internal only (no ingress) | — |
Pre-loaded Grafana dashboards:
| Dashboard | ID |
|---|---|
| Kubernetes Cluster | 7249 |
| Node Exporter Full | 1860 |
| Loki Kubernetes Logs | 13639 |
See
Applications/monitoring/README.mdfor full component details, in-cluster service URLs, and lessons learned.
The argocd-install.sh script offers three options at runtime:
| Option | Action |
|---|---|
1 |
Install ArgoCD (or reinstall) |
2 |
Upgrade ArgoCD to a new version |
3 |
Delete ArgoCD and remove all CRDs |
argocd app list # List all applications
argocd app get <app-name> # App health + sync status
argocd app sync <app-name> # Trigger manual sync
argocd app rollback <app-name> # Roll back to previous version
argocd app delete <app-name> # Delete app + cascade resources# ArgoCD-specific (pods, ingress, logs)
bash GitOps-Argocd-Setup/argocd-diag.sh
# Cluster-level
kubectl get nodes
kubectl get pods -A
kubectl get ingress -A
# Watch monitoring rollout
kubectl get pods -n ns-monitoring -wDeveloper → git push → GitHub Repo
↓
ArgoCD detects diff (every 3 min, or webhook)
↓
Auto-sync to Kind cluster
(prune: true · selfHeal: true)
↓
App is Synced + Healthy ✅
Run the bootstrap script and it will print installed versions at the end:
Docker: docker version ...
kubectl: Client Version ...
kind: kind v...
Terraform: Terraform v...
AWS CLI: aws-cli/2.x.x
ArgoCD CLI: argocd v...
| Tool | Purpose | Installed by |
|---|---|---|
| Docker | Container runtime (required by Kind) | devops-bootstrap.sh |
| kubectl | Kubernetes CLI | devops-bootstrap.sh |
| kind | Kubernetes-in-Docker | devops-bootstrap.sh |
| Terraform | Infrastructure as Code | devops-bootstrap.sh |
| AWS CLI v2 | AWS cloud operations | devops-bootstrap.sh |
| ArgoCD CLI | GitOps app management | devops-bootstrap.sh |
| NGINX Ingress | In-cluster ingress routing | Step 3 above |