Skip to content

Wildcard TLS via cert-manager + DNS-01/Cloudflare

Date: 2026-03-23 Status: Accepted Context: Providing HTTPS for all team subdomains (e.g., team.prod.fontysvenlo.dev) automatically

Decision

Use cert-manager with Let's Encrypt and the DNS-01 challenge via Cloudflare to provision wildcard TLS certificates. A single wildcard cert per domain is replicated to all namespaces via ExternalSecrets.

Architecture

graph TB
    cm["cert-manager"] -->|"ACME DNS-01"| le["Let's Encrypt"]
    le -->|"via Cloudflare API"| cm
    cm --> certs["Wildcard certs<br/>*.prod.fontysvenlo.dev<br/>*.spohf.fontysvenlo.dev"]
    certs -->|"ExternalSecrets<br/>replication"| ns["All workload namespaces<br/>prj2-*, spohf-*, harbor,<br/>argocd, monitoring, ..."]
    ns --> traefik["Traefik<br/>terminates TLS"]

Rationale

Why wildcard certificates?

  • Dynamic subdomains — new teams get subdomains ({team}.prod.fontysvenlo.dev) without any certificate provisioning step. The wildcard covers them all.
  • Simplicity — one cert to manage per domain instead of one per team/service.

Why DNS-01 challenge?

  • Required for wildcards — HTTP-01 challenges cannot issue wildcard certificates (ACME specification limitation).
  • fontysvenlo.dev already on Cloudflare — DNS-01 via the Cloudflare API was the natural path.

Why replicate via ExternalSecrets?

  • cert-manager provisions the cert in its own namespace. Traefik and workloads in other namespaces need access to it. ExternalSecrets handles this cross-namespace distribution declaratively.

Alternatives Considered

HTTP-01 per-service certificates

  • ✅ No DNS provider dependency
  • ❌ Cannot issue wildcard certs — would need a cert per team subdomain
  • ❌ Provisioning delay when adding new teams
  • Rejected: Doesn't support our dynamic subdomain model

Per-namespace cert-manager issuers

  • ✅ Each namespace manages its own cert
  • ❌ More CRDs, more issuers, more potential for misconfiguration
  • ❌ Each namespace would need Cloudflare API credentials
  • Rejected: More moving parts for no benefit

Consequences

Positive

  • New teams get HTTPS automatically — zero TLS configuration per team
  • Single renewal point — cert-manager handles rotation automatically
  • Works regardless of ingress reachability (DNS-01 doesn't need inbound HTTP)

Negative

  • Dependency on Cloudflare — Cloudflare API token must be maintained as a manual secret (not in git)
  • Single wildcard cert is a shared failure point — if renewal fails, all services lose TLS
  • Cross-namespace replication adds a layer of indirection