From 646b165e420b36c0e1b42e2c5b1f5135a0b5b451 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Tue, 25 Aug 2026 20:43:12 +1000 Subject: [PATCH] cheeztv: terminate public cheeztv.unkin.net TLS with the LE *.unkin.net wildcard Public-facing cheeztv.unkin.net was terminating TLS with an internal Vault PKI leaf (cheeztv-tls, cluster-issuer vault-issuer), which browsers do not trust. Per-host Let's Encrypt DNS-01 for cheeztv.unkin.net fails NOTAUTH because the public zone only delegates _acme-challenge.unkin.net -> acme.unkin.net; a single *.unkin.net wildcard validates against that one CNAME and needs no per-host records. Staging issuance of *.unkin.net was verified end-to-end (~70s: Present by the recursive-nameserver controller -> Order valid -> Certificate Ready). - Add apps/base/cheeztv/certificate.yaml: cert-manager Certificate cheeztv-wildcard-tls (dnsNames *.unkin.net, ClusterIssuer letsencrypt PROD, secret cheeztv-wildcard-tls) in the cheeztv namespace. - Point the public cheeztv gateway's https listener certificateRefs at cheeztv-wildcard-tls and drop its cert-manager.io vault-issuer annotations. - Keep the cheeztv-internal gateway (cheeztv.k8s.syd1.au.unkin.net) on vault-issuer / cheeztv-internal-tls, unchanged. - Register certificate.yaml in the cheeztv kustomization. --- apps/base/cheeztv/certificate.yaml | 21 +++++++++++++++++++++ apps/base/cheeztv/gateway.yaml | 10 ++++------ apps/base/cheeztv/kustomization.yaml | 1 + 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 apps/base/cheeztv/certificate.yaml diff --git a/apps/base/cheeztv/certificate.yaml b/apps/base/cheeztv/certificate.yaml new file mode 100644 index 0000000..9ddf2aa --- /dev/null +++ b/apps/base/cheeztv/certificate.yaml @@ -0,0 +1,21 @@ +--- +# Public-facing cheeztv.unkin.net terminates TLS with a real Let's Encrypt cert +# instead of the internal Vault PKI leaf. A single *.unkin.net wildcard is used +# so DNS-01 validates against the one delegated _acme-challenge.unkin.net CNAME +# and no per-host _acme-challenge records are required. The cheeztv gateway's +# https listener consumes this secret; cheeztv-internal keeps its Vault leaf. +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: cheeztv-wildcard-tls + namespace: cheeztv +spec: + secretName: cheeztv-wildcard-tls + privateKey: + size: 4096 + dnsNames: + - "*.unkin.net" + issuerRef: + name: letsencrypt + kind: ClusterIssuer + group: cert-manager.io diff --git a/apps/base/cheeztv/gateway.yaml b/apps/base/cheeztv/gateway.yaml index 9ceec36..43f8fed 100644 --- a/apps/base/cheeztv/gateway.yaml +++ b/apps/base/cheeztv/gateway.yaml @@ -1,17 +1,15 @@ --- # Friendly public hostname for the kids instance, cheeztv.unkin.net. Same # internal-Traefik + external-dns pattern as logviewer.unkin.net: external-dns -# publishes the A record at the internal LB VIP (198.18.200.4) and cert-manager -# mints cheeztv-tls (CN cheeztv.unkin.net) off the Vault-PKI cluster issuer. +# publishes the A record at the internal LB VIP (198.18.200.4). Public TLS is +# terminated with the real Let's Encrypt *.unkin.net wildcard from +# certificate.yaml (secret cheeztv-wildcard-tls), not the Vault PKI issuer. apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: labels: traefik.io/instance: internal annotations: - cert-manager.io/cluster-issuer: vault-issuer - cert-manager.io/common-name: cheeztv.unkin.net - cert-manager.io/private-key-size: "4096" external-dns.alpha.kubernetes.io/hostname: cheeztv.unkin.net external-dns.alpha.kubernetes.io/target: 198.18.200.4 name: cheeztv @@ -37,7 +35,7 @@ spec: certificateRefs: - group: "" kind: Secret - name: cheeztv-tls + name: cheeztv-wildcard-tls mode: Terminate --- # Cluster hostname variant, mirroring fafflix's jellyfin.k8s.syd1.au.unkin.net diff --git a/apps/base/cheeztv/kustomization.yaml b/apps/base/cheeztv/kustomization.yaml index 26efe34..737c7d2 100644 --- a/apps/base/cheeztv/kustomization.yaml +++ b/apps/base/cheeztv/kustomization.yaml @@ -22,5 +22,6 @@ resources: - service.yaml - valkey.yaml - vmpodscrape.yaml + - certificate.yaml - gateway.yaml - httproute.yaml