diff --git a/templates/cluster-issuer.yaml b/templates/cluster-issuer.yaml index be58fa2..5eb9c3f 100644 --- a/templates/cluster-issuer.yaml +++ b/templates/cluster-issuer.yaml @@ -1,19 +1,32 @@ {{- if .Values.tenant.domain }} +# letsencrypt-prod ClusterIssuer — DNS-01 challenge via Cloudflare. +# +# Multi-zone: the solver has NO `selector.dnsZones` restriction. The +# tenant's Cloudflare token typically covers many zones (a tenant with +# 41 owned domains is normal); we let cert-manager pick whichever zone +# matches the requested host. The token's access is the natural +# boundary — if it can't write a zone, the challenge fails loudly. +# +# Earlier the solver was scoped to `.Values.tenant.domain` only, which +# made instances on ANY other tenant-owned domain unable to issue (the +# `app.havari.me` symptom on a tenant whose primary domain is +# `4th.online`). Dropping the selector unifies single-zone and +# multi-zone tenants under one issuer. +# +# The cloudflare-api-token Secret is NOT in this chart. Tower +# kubectl-applies it into cert-manager ns at Connect time using the +# tenant's per-tenant Vault credential (v3/tenants//cloudflare-token). +# The chart references it by name only. +# +# Sync wave: needs to land AFTER cert-manager's CRDs are installed +# (cert-manager dep installs first); Argo's default ordering by kind +# handles this. apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod labels: app.kubernetes.io/managed-by: cluster-platform-v3 - annotations: - # Argo applies resources in ascending sync-wave order. cert-manager - # subchart resources land in the default wave (0); we push CR - # consumers to wave 5 so the CRDs (Certificate, ClusterIssuer) the - # cert-manager Helm subchart installs are present by the time - # Argo apply hits these. Without this, Argo discovery fails on - # the first sync with "no matches for kind" because Argo applies - # the bundle in one pass and CRD discovery is cached. - argocd.argoproj.io/sync-wave: "5" spec: acme: email: {{ required "acme.email is required" .Values.acme.email | quote }} @@ -26,7 +39,4 @@ spec: apiTokenSecretRef: name: {{ .Values.secrets.cloudflareTokenSecret.name | quote }} key: {{ .Values.secrets.cloudflareTokenSecret.key | quote }} - selector: - dnsZones: - - {{ .Values.tenant.domain | quote }} {{- end }}