ArgoCD GitOps repository. Contains all application and platform definitions deployed to Kubernetes clusters.
The companion infrastructure repository (Terraform + Minikube) bootstraps ArgoCD and points it here.
ArgoCD manages itself entirely through this repo via an App-of-Apps pattern:
[Terraform] ──bootstraps──> bootstrap (ArgoCD Application)
│
└──watches──> clusters/local/
│
┌─────────┴──────────┐
▼ ▼
platform demo (+ future apps)
│
platform/local/
(ingress-nginx, ...)
- Terraform creates a single seed Application called
bootstrap bootstrapreadsbootstrap/local.yamland creates thelocalApplicationlocalreadsclusters/local/and creates one Application per file found there- Each Application then manages its own resources on the cluster
gitops/
│
├── bootstrap/
│ └── local.yaml # "local" ArgoCD Application (watches clusters/local/)
│
├── clusters/
│ └── local/ # One directory per cluster environment
│ ├── demo.yml # Deploys the demo Helm chart (values-local.yaml)
│ └── platform.yml # Deploys platform tools (points to platform/local/)
│
├── platform/
│ └── local/ # Platform tools for the local cluster
│ └── ingress-nginx.yml # ArgoCD Application: ingress-nginx Helm release
│
└── apps/
└── demo/ # Helm chart for the demo nginx app
├── Chart.yaml
├── values.yaml # Default values (production-ish baseline)
├── values-local.yaml # Local overrides (smaller resources, demo.local host)
└── templates/
├── deployment.yaml
├── service.yaml
└── ingress.yaml
- Create a Helm chart under
apps/<your-app>/:
apps/your-app/
├── Chart.yaml
├── values.yaml # sensible defaults, treat as prod baseline
├── values-local.yaml # local overrides
└── templates/
└── ...
- Add an ArgoCD Application in
clusters/local/your-app.yml:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: your-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/IntegratedDynamic/gitops.git
targetRevision: main
path: apps/your-app
helm:
valueFiles:
- values-local.yaml
destination:
server: https://kubernetes.default.svc
namespace: your-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueArgoCD picks it up automatically — no manual sync needed.
Say you're adding staging:
-
Add environment values for each app that needs overrides:
apps/demo/values-staging.yaml -
Add platform tools for the new cluster:
platform/staging/ingress-nginx.yml # e.g. with LoadBalancer instead of NodePort -
Add cluster entry point in
clusters/staging/:clusters/staging/demo.yml # same structure as local, different valueFiles clusters/staging/platform.yml # points to platform/staging/ -
Add a bootstrap manifest in
bootstrap/:bootstrap/staging.yaml # same structure as local.yaml, points to clusters/staging/ -
Point Terraform (or your cluster provisioner) at
bootstrap/staging.yamlto seed it.
Only the values files and cluster entry points differ — the charts themselves are never duplicated.
Platform tools are ArgoCD Applications that install Helm charts from external repositories.
Add a file per tool under platform/<env>/:
# platform/local/cert-manager.yml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cert-manager
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.jetstack.io
chart: cert-manager
targetRevision: v1.17.0
helm:
values: |
installCRDs: true
destination:
server: https://kubernetes.default.svc
namespace: cert-manager
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=trueThe platform App-of-Apps picks it up automatically.
After mise run reset && mise run dev in the infrastructure repo:
# Add demo.local to /etc/hosts
echo "$(minikube ip) demo.local" | sudo tee -a /etc/hosts
# Check it's up
curl http://demo.local