# fastpass — ArgoCD Bootstrap This document covers the manual steps required to bootstrap ArgoCD on the `fastpass` cluster. After these steps, all further changes are made via Git. **Prerequisites:** - All 6 Talos nodes `Ready` (`kubectl get nodes`) - Cilium healthy (`cilium status --wait`) - IP pools applied (`kubectl get ciliumloadbalancerippool`) - `city-hall` has `helm`, `kubectl`, and `talosctl` installed - SSH keypair for ArgoCD → Gitea exists at `/home/wed/.ssh/argocd_gitea` --- ## Step 1 — Create the argocd namespace ```bash kubectl apply -f cluster/argocd/namespace.yaml ``` --- ## Step 2 — Add Gitea to ArgoCD known hosts ArgoCD refuses SSH connections to unknown hosts. Pre-populate the known hosts configmap before ArgoCD starts: ```bash ssh-keyscan -t ed25519 gitea.mk-labs.cloud | \ kubectl create configmap argocd-ssh-known-hosts-cm \ --namespace argocd \ --from-file=ssh_known_hosts=/dev/stdin \ --dry-run=client -o yaml | kubectl apply -f - ``` --- ## Step 3 — Create the Gitea repo secret This is the only credential that must be manually created. Once ESO is running, secrets will be managed via 1Password. For now, create it directly: ```bash kubectl create secret generic gitea-repo \ --namespace argocd \ --from-literal=type=git \ --from-literal=url=git@gitea.mk-labs.cloud:rblundon/homelab.git \ --from-file=sshPrivateKey=/home/wed/.ssh/argocd_gitea kubectl label secret gitea-repo -n argocd \ argocd.argoproj.io/secret-type=repository ``` Verify: ```bash kubectl -n argocd get secret gitea-repo ``` --- ## Step 4 — Install ArgoCD via Helm ```bash helm repo add argo https://argoproj.github.io/argo-helm helm repo update helm upgrade --install argocd argo/argo-cd \ --namespace argocd \ --create-namespace \ --version 7.8.23 \ --values cluster/argocd/values.yaml \ --wait ``` Wait for all ArgoCD pods to be ready: ```bash kubectl -n argocd get pods --watch ``` --- ## Step 5 — Get the initial admin password ```bash kubectl -n argocd get secret argocd-initial-admin-secret \ -o jsonpath='{.data.password}' | base64 -d; echo ``` Access the UI via port-forward (ingress-nginx isn't installed yet at this point): ```bash kubectl port-forward svc/argocd-server -n argocd 8080:80 ``` Browse to http://localhost:8080 — login with `admin` and the password above. --- ## Step 6 — Apply the app-of-apps This is the second and final manual `kubectl apply`. It hands control to ArgoCD: ```bash kubectl apply -n argocd -f cluster/argocd/apps-of-apps.yaml ``` From this point, all changes are made via Git. ArgoCD will begin syncing `cluster/platform/` and `cluster/applications/` automatically. Watch the sync: ```bash kubectl -n argocd get applications --watch ``` --- ## Step 7 — Approve CSRs After nodes join and kubelet starts requesting certs, approve pending CSRs: ```bash kubectl get csr --no-headers | awk '{print $1}' | xargs kubectl certificate approve ``` Run this periodically until no pending CSRs remain. --- ## Expected platform sync order Apps sync in wave order via `argocd.argoproj.io/sync-wave` annotations: | Wave | App | |------|-----| | 0 | apps-of-apps (root) | | 1 | cert-manager CRDs | | 2 | cert-manager, external-secrets | | 3 | ingress-nginx | | 4 | external-dns | | 5+ | application workloads | --- ## Troubleshooting **ArgoCD can't reach Gitea:** ```bash kubectl -n argocd logs deployment/argocd-repo-server | grep -i "error\|ssh" ``` Check that the `gitea-repo` secret exists and the known hosts configmap has `gitea.mk-labs.cloud`. **App stuck in `Unknown` state:** ```bash kubectl -n argocd get application -o yaml | grep -A10 "conditions" ``` **self-reference loop (app syncing itself):** Ensure `apps-of-apps.yaml` uses `include: "*/application.yaml"` with `recurse: true` — this prevents ArgoCD from picking up its own manifest. **ArgoCD pruning itself:** The `argocd` namespace Applications must have `prune: false`. Never enable prune on any Application that manages the `argocd` namespace. **Helm valueFiles field:** The correct field name is `valueFiles` (plural). `valuesFile` and `valuesFiles` are silently ignored — ArgoCD syncs green but your values aren't applied. --- ## Post-bootstrap Once ingress-nginx and cert-manager are synced: - ArgoCD UI available at https://argocd.local.mk-labs.cloud - Change the admin password: `argocd account update-password` - Authentik OIDC: uncomment the `oidc.config` block in `values.yaml` once the ArgoCD provider is configured in Authentik - Migrate `gitea-repo` secret to ESO once 1Password Connect is running