Post

cert-manager

cert-manager

cert-manager

Issues and renews TLS certificates for every ingress in the cluster. Deployed via the official Helm chart into the cert-manager namespace with 3 controller replicas.

Configuration

values.yaml sets:

  • installCRDs: false — CRDs are managed separately from the Helm release.
  • --dns01-recursive-nameservers=1.1.1.1:53,9.9.9.9:53 plus --dns01-recursive-nameservers-only — DNS-01 challenge lookups go straight to Cloudflare and Quad9 instead of the pod’s default resolver, avoiding split-horizon DNS surprises.
  • podDnsPolicy: None with an explicit podDnsConfig pointing at the same two nameservers, for the same reason.

Issuer

A single ClusterIssuer named letsencrypt-production handles all certificates, using Let’s Encrypt’s production ACME endpoint with a DNS-01 challenge solved via the Cloudflare provider (scoped to the iot-proxmox.net zone). The Cloudflare API token is stored in a Secret (cloudflare-token-secret, key cloudflare-token) referenced by the issuer — its value is not stored in this repo.

Certificates

Every namespace that terminates TLS requests its own local-example-com Certificate resource against the shared wildcard, rather than sharing one certificate/Secret across namespaces (Kubernetes Secrets don’t cross namespace boundaries). All of them currently issue the same *.prod-k3s.iot-proxmox.net wildcard into a namespace-local local-example-com-tls Secret:

NamespaceSecret
defaultlocal-example-com-tls
traefiklocal-example-com-tls
argocdlocal-example-com-tls

Traefik’s IngressRoute resources reference their namespace’s copy of this Secret for TLS termination; Traefik itself always speaks plain HTTP to backend services.

This post is licensed under CC BY 4.0 by the author.