From d0887ac6487a88879e6611734894d49dd7785a4f Mon Sep 17 00:00:00 2001 From: Nik Afiq Date: Thu, 23 Jul 2026 18:20:54 +0900 Subject: [PATCH] fix: Argo CD bootstrap normalization -- adopt cert-manager/Authentik config, fix policy drift Stage 5 + part of Stage 6/7 of REFACTOR_PLAN.md. This is the highest-risk stage per the plan -- these Applications are NOT to be pushed/synced blindly. Each needs `kubectl diff` against live state one at a time before enabling. New Applications (previously-live resources with zero GitOps coverage): - cert-manager-config.yaml (manifests/cert-manager: both ClusterIssuers + the internal CA Certificate -- every TLS cert in the cluster depends on these, and nothing currently restores them on a cold rebuild). - authentik-config.yaml (manifests/authentik: ingress, proxy outpost, middleware -- raw manifests only, low risk). - authentik.yaml (the Authentik Helm chart itself): sync is deliberately left MANUAL and targetRevision is a REPLACE_ME placeholder -- I don't have a safe way to read the live chart version (`helm list -n authentik`), and guessing wrong risks an unwanted upgrade/downgrade of the SSO IdP gating Argo CD/ Grafana/Gitea logins. Needs your input before this one goes anywhere. - network.yaml: widens coverage to the 4 non-sealed files in manifests/network (ddns-cronjob, glances-debian-ingress, traefik-dashboard-ingress, watch-party-ingress) that were previously invisible to Argo CD; keeps network-secrets.yaml scoped to *-sealed.yaml only. Fixes: - homeassistant.yaml: destination.namespace was "homeassistant" (empty, unused) while the actual resources are hardcoded to "default" -- corrected, dropped CreateNamespace=true. The old empty namespace isn't auto-deleted (prune: false); safe to remove by hand if desired. - gitea-backup.yaml: added the missing Namespace object (nothing created "gitea-backup" before); replaced a cluster-wide ClusterRole/ClusterRoleBinding granting pods/exec everywhere with a Role/RoleBinding scoped to the `gitea` namespace, matching what the backup script actually execs into. NOTE: this is already under active sync via gitea-secrets.yaml (selfHeal: true, prune: false) -- once pushed, the old ClusterRole/ClusterRoleBinding will need manual `kubectl delete` since Argo CD won't prune them. - Added sync-wave "-2" to cert-manager/sealed-secrets Applications so their CRDs land before consumers (matches the existing -1/0 wave pattern). - Normalized targetRevision HEAD -> main on home-services/otel-collector/tempo. - Normalized sync policy per your decision: home-services/otel-collector/tempo prune true -> false; pihole/pihole-debian selfHeal false -> true (repo-wide consistency, per your call on finding #18). Verified: kubeconform valid across all manifests + Argo CD Application objects. Co-Authored-By: Claude Sonnet 5 --- argocd/apps/authentik-config.yaml | 20 +++++++++++++++++ argocd/apps/authentik.yaml | 33 ++++++++++++++++++++++++++++ argocd/apps/cert-manager-config.yaml | 22 +++++++++++++++++++ argocd/apps/cert-manager.yaml | 2 ++ argocd/apps/home-services.yaml | 4 ++-- argocd/apps/homeassistant.yaml | 6 ++--- argocd/apps/network.yaml | 23 +++++++++++++++++++ argocd/apps/otel-collector.yaml | 4 ++-- argocd/apps/pihole-debian.yaml | 2 +- argocd/apps/pihole.yaml | 2 +- argocd/apps/sealed-secrets.yaml | 2 ++ argocd/apps/tempo.yaml | 4 ++-- manifests/gitea/gitea-backup.yaml | 13 ++++++++--- 13 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 argocd/apps/authentik-config.yaml create mode 100644 argocd/apps/authentik.yaml create mode 100644 argocd/apps/cert-manager-config.yaml create mode 100644 argocd/apps/network.yaml diff --git a/argocd/apps/authentik-config.yaml b/argocd/apps/authentik-config.yaml new file mode 100644 index 0000000..da5ac35 --- /dev/null +++ b/argocd/apps/authentik-config.yaml @@ -0,0 +1,20 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: authentik-config + namespace: argocd +spec: + project: default + source: + repoURL: https://gitea.nik4nao.com/nik/homelab.git + targetRevision: main + path: manifests/authentik + directory: + include: '*.yaml' + destination: + server: https://kubernetes.default.svc + namespace: authentik + syncPolicy: + automated: + prune: false + selfHeal: true diff --git a/argocd/apps/authentik.yaml b/argocd/apps/authentik.yaml new file mode 100644 index 0000000..57c8109 --- /dev/null +++ b/argocd/apps/authentik.yaml @@ -0,0 +1,33 @@ +# NEEDS YOUR INPUT before first sync: targetRevision below is a placeholder. +# Run `helm list -n authentik` on the live cluster and set this to the chart +# version actually deployed (installed by hand per the header comment in +# values/authentik.yaml) -- Authentik is the SSO IdP gating Argo CD/Grafana/ +# Gitea logins, so adopting it into GitOps with the wrong version could +# trigger an unwanted live chart upgrade/downgrade on first sync. Sync is +# left manual (no `automated:` block) until you've confirmed this and diffed +# with `kubectl diff` / `argocd app diff`. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: authentik + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "-1" +spec: + project: default + sources: + - repoURL: https://charts.goauthentik.io + chart: authentik + targetRevision: "REPLACE_ME" + helm: + valueFiles: + - $values/values/authentik.yaml + - repoURL: https://gitea.nik4nao.com/nik/homelab.git + targetRevision: main + ref: values + destination: + server: https://kubernetes.default.svc + namespace: authentik + syncPolicy: + syncOptions: + - CreateNamespace=true diff --git a/argocd/apps/cert-manager-config.yaml b/argocd/apps/cert-manager-config.yaml new file mode 100644 index 0000000..0985ace --- /dev/null +++ b/argocd/apps/cert-manager-config.yaml @@ -0,0 +1,22 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: cert-manager-config + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "-1" +spec: + project: default + source: + repoURL: https://gitea.nik4nao.com/nik/homelab.git + targetRevision: main + path: manifests/cert-manager + directory: + include: '*.yaml' + destination: + server: https://kubernetes.default.svc + namespace: cert-manager + syncPolicy: + automated: + prune: false + selfHeal: true diff --git a/argocd/apps/cert-manager.yaml b/argocd/apps/cert-manager.yaml index d8f59b2..e904d4f 100644 --- a/argocd/apps/cert-manager.yaml +++ b/argocd/apps/cert-manager.yaml @@ -3,6 +3,8 @@ kind: Application metadata: name: cert-manager namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "-2" spec: project: default sources: diff --git a/argocd/apps/home-services.yaml b/argocd/apps/home-services.yaml index ed3ce94..cc9dfe7 100644 --- a/argocd/apps/home-services.yaml +++ b/argocd/apps/home-services.yaml @@ -9,14 +9,14 @@ spec: project: default source: repoURL: https://gitea.nik4nao.com/nik/homelab.git - targetRevision: HEAD + targetRevision: main path: manifests/home-services destination: server: https://kubernetes.default.svc namespace: home-services syncPolicy: automated: - prune: true + prune: false selfHeal: true syncOptions: - CreateNamespace=true \ No newline at end of file diff --git a/argocd/apps/homeassistant.yaml b/argocd/apps/homeassistant.yaml index 8b024bc..c8617a5 100644 --- a/argocd/apps/homeassistant.yaml +++ b/argocd/apps/homeassistant.yaml @@ -11,10 +11,8 @@ spec: path: manifests/homeassistant destination: server: https://kubernetes.default.svc - namespace: homeassistant + namespace: default syncPolicy: automated: prune: false - selfHeal: true - syncOptions: - - CreateNamespace=true \ No newline at end of file + selfHeal: true \ No newline at end of file diff --git a/argocd/apps/network.yaml b/argocd/apps/network.yaml new file mode 100644 index 0000000..d8f31e3 --- /dev/null +++ b/argocd/apps/network.yaml @@ -0,0 +1,23 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: network + namespace: argocd +spec: + project: default + source: + repoURL: https://gitea.nik4nao.com/nik/homelab.git + targetRevision: main + path: manifests/network + directory: + exclude: '*-sealed.yaml' + include: '*.yaml' + destination: + server: https://kubernetes.default.svc + namespace: pihole + syncPolicy: + automated: + prune: false + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/argocd/apps/otel-collector.yaml b/argocd/apps/otel-collector.yaml index 221b67c..9fa4313 100644 --- a/argocd/apps/otel-collector.yaml +++ b/argocd/apps/otel-collector.yaml @@ -14,14 +14,14 @@ spec: valueFiles: - $values/values/otel-collector.yaml - repoURL: https://gitea.nik4nao.com/nik/homelab.git - targetRevision: HEAD + targetRevision: main ref: values destination: server: https://kubernetes.default.svc namespace: monitoring syncPolicy: automated: - prune: true + prune: false selfHeal: true syncOptions: - CreateNamespace=false diff --git a/argocd/apps/pihole-debian.yaml b/argocd/apps/pihole-debian.yaml index 34da1c5..6146849 100644 --- a/argocd/apps/pihole-debian.yaml +++ b/argocd/apps/pihole-debian.yaml @@ -21,6 +21,6 @@ spec: syncPolicy: automated: prune: false - selfHeal: false + selfHeal: true syncOptions: - CreateNamespace=true \ No newline at end of file diff --git a/argocd/apps/pihole.yaml b/argocd/apps/pihole.yaml index 38d327c..c39b9fe 100644 --- a/argocd/apps/pihole.yaml +++ b/argocd/apps/pihole.yaml @@ -21,6 +21,6 @@ spec: syncPolicy: automated: prune: false - selfHeal: false + selfHeal: true syncOptions: - CreateNamespace=true \ No newline at end of file diff --git a/argocd/apps/sealed-secrets.yaml b/argocd/apps/sealed-secrets.yaml index 665151e..18f3abd 100644 --- a/argocd/apps/sealed-secrets.yaml +++ b/argocd/apps/sealed-secrets.yaml @@ -3,6 +3,8 @@ kind: Application metadata: name: sealed-secrets namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "-2" spec: project: default sources: diff --git a/argocd/apps/tempo.yaml b/argocd/apps/tempo.yaml index a5fc981..50eb23a 100644 --- a/argocd/apps/tempo.yaml +++ b/argocd/apps/tempo.yaml @@ -14,14 +14,14 @@ spec: valueFiles: - $values/values/tempo.yaml - repoURL: https://gitea.nik4nao.com/nik/homelab.git - targetRevision: HEAD + targetRevision: main ref: values destination: server: https://kubernetes.default.svc namespace: monitoring syncPolicy: automated: - prune: true + prune: false selfHeal: true syncOptions: - CreateNamespace=false diff --git a/manifests/gitea/gitea-backup.yaml b/manifests/gitea/gitea-backup.yaml index 003711e..d7aa644 100644 --- a/manifests/gitea/gitea-backup.yaml +++ b/manifests/gitea/gitea-backup.yaml @@ -2,15 +2,21 @@ # Delete: kubectl delete -f manifests/gitea/gitea-backup.yaml # Description: CronJob that backs up Gitea to NFS every 7 days, with RBAC and PV/PVC. apiVersion: v1 +kind: Namespace +metadata: + name: gitea-backup +--- +apiVersion: v1 kind: ServiceAccount metadata: name: gitea-backup namespace: gitea-backup --- apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole +kind: Role metadata: name: gitea-backup + namespace: gitea rules: - apiGroups: [""] resources: ["pods"] @@ -20,15 +26,16 @@ rules: verbs: ["create"] --- apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: name: gitea-backup + namespace: gitea subjects: - kind: ServiceAccount name: gitea-backup namespace: gitea-backup roleRef: - kind: ClusterRole + kind: Role name: gitea-backup apiGroup: rbac.authorization.k8s.io ---