Reviewed-on: #1
GitOps on Haven — Deployment Draft
Draft only. Nothing below is applied to the cluster yet. Diagrams are [Excalidraw JSON] (import at https://excalidraw.com) — static previews included as PNG. Create the repo before running any commands.
1. Decisions
| Decision | Value | Why |
|---|---|---|
| Tool | Argo CD | Best UI (app dependency graph, live-vs-git diff, rollback). Flux's UI (Weave GitOps) is stalled post-Weaveworks; community alternative is Capacitor. |
| Git remote | Gitea git.ivanch.me/ivanch/haven |
Repo you'll create. Gitea is a first-class Argo CD source. |
| Layout | App-of-apps | A single root Argo Application watches a folder of app manifests; each app manifests as a child Application. One place to add/remove apps. |
| Secrets | No change. Keep raw env in manifests initially, migrate to ESO/Vaultwarden later. | Argo CD can't write Secret contents itself — value must live in git or come from a controller. Never commit real secrets. |
| Access | Ingress argocd.haven, internal-only (nginx class, no TLS/cert-manager) + admin password via kubectl |
Matches your internal-app convention (notepad, openwebui, etc.). |
| Repo structure | New gitops repo (clean, standalone). Your current spec folder stays untouched — migrate later if desired. |
Avoids mixing with the haven folder used by Gitea Actions CI. |
2. Repo layout (gitops/)
gitops/
├── bootstrap/
│ ├── namespaces.yaml # cluster namespaces
│ ├── argocd-install/ # Argo CD install manifests + ingress
│ └── root-app.yaml # root Application watching apps/root
├── apps/
│ ├── root/
│ │ ├── kustomization.yaml # points to applicationset.yaml
│ │ └── applicationset.yaml# auto-discovers apps/*/*.yaml
│ └── <namespace>/ # e.g., default/, media/, monitoring/
│ ├── <app-1>.yaml # all-in-one manifest per app
│ └── <app-2>.yaml
To add a new app: simply drop <app>.yaml into the appropriate apps/<namespace>/ folder. The ApplicationSet automatically generates an Argo CD Application for it.
3. Manual bootstrap (run once, by hand)
# Install Argo CD — declarative kustomize install (no Helm CLI, no curl pipes).
# Renders 59 resources from the official argo-cd manifests repo, pinned via ?ref=
kubectl.exe --kubeconfig=C:\Users\ivanch\.kube\config apply -k bootstrap/argocd-install
# retrieve the initial admin password
kubectl.exe --kubeconfig=C:\Users\ivanch\.kube\config -n argocd get secret argocd-initial-admin-secret \
-o jsonpath='{.data.password}' | base64 -d
# one-time: point the root app at Gitea (requires the repo to exist first)
kubectl.exe --kubeconfig=C:\Users\ivanch\.kube\config apply -f bootstrap/root-app.yaml
Version pinning: ?ref=stable in bootstrap/argocd-install/kustomization.yaml
tracks the stable branch; pin a tag (?ref=v3.1.0) once settled. Component
customization goes through patches: in that same kustomization (example
commented in the file), not by editing rendered output.
After that, every change is: git push → Argo syncs. kubectl only for debugging.
4. Key manifests
bootstrap/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root
namespace: argocd
finalizers: [resources-finalizer.argocd.argoproj.io]
spec:
project: default
source:
repoURL: https://git.ivanch.me/ivanch/haven.git
targetRevision: main
path: apps/root
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
apps/root/applicationset.yaml — Uses the Git Files generator to discover any apps/*/*.yaml file and automatically generate an Argo CD Application pointing directly to that app file within the respective namespace.
5. Ingress (internal-only, per Haven convention)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server
namespace: argocd
spec:
ingressClassName: nginx
rules:
- host: argocd.haven
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port: { number: 80 }
6. Diagrams (Excalidraw JSON)
Two diagrams are included as .excalidraw files — open https://excalidraw.com
and drop the file onto the canvas to view/edit:
excalidraw/haven-gitops-flow.excalidraw— the flow: git push → Gitea → Argo CD → k3s, with Gitea Actions CI reduced to image build/push only.excalidraw/haven-gitops-tree.excalidraw— the app-of-apps tree: root app → child Applications (notepad, openwebui, paperless, vaultwarden, argocd itself, and infra deferred to a later phase).
7. Migration plan
Phase 0 (this draft) → Phase 1: install Argo CD + root app, convert 1 pilot app
(suggest notepad — simple, stateless-ish, single PVC) → Phase 2: onboard the
rest of default ns → Phase 3: infra components (ingress-nginx, cert-manager,
ESO) — do these last; they're the ones that can break the cluster if a sync
goes wrong → Phase 4: delete the old haven spec folder once Argo is the source
of truth.