# ADR-0006 — TLS: cert-manager + Let's Encrypt (DNS-01) - Status: Accepted - Date: 2026-08-15 - Serves: R-TLS-01, R-TLS-02, R-TLS-03, R-DNS-01 - Supersedes: — ## Context Every service needs a **trusted, non-self-signed** certificate, auto issued/renewed/revoked, including **internal-only** services (which must not be forced public just to validate a cert). Wildcard coverage of `*.home.keithjackson.dev` would make onboarding certificate-free. ## Decision Use **cert-manager** with **Let's Encrypt** (a publicly trusted, free, automatable CA) via the **ACME DNS-01** challenge against the `keithjackson.dev` DNS zone (Cloudflare or equivalent, OQ-4). DNS-01 validates domain control without exposing the service and enables **wildcard** certs. Default: a **wildcard `*.home.keithjackson.dev`** certificate terminated at the Gateway ([09](../docs/09-dns-and-ingress.md)), with per-service certificates available where isolation warrants. Provide both `letsencrypt-staging` (bring-up) and `letsencrypt-prod` ClusterIssuers. ## Alternatives considered - **HTTP-01 challenge** — rejected: requires public exposure of each service; fails R-TLS-03 for internal-only services and can't do wildcards. - **Self-signed / private CA** — rejected: explicitly disallowed (R-TLS-01, "not self-signed"). - **Paid CA** — unnecessary; Let's Encrypt is trusted and free. - **ZeroSSL/other ACME CA** — viable fallback; Let's Encrypt chosen as default. ## Consequences - Internal services get real, trusted certs; wildcard makes onboarding certificate-free (default). - Requires a DNS-provider API token scoped for DNS-01, stored SOPS-encrypted (OQ-4, ADR-0007). - Certificate expiry/issuance failures are alert conditions (R-OBS-04). - Internal clients trust the certs with no custom-CA distribution; split-horizon DNS serves the same cert internally and externally. - Optional future mTLS between workloads is a separate concern (Cilium/mesh), not covered here.