Skip to content

cert-manager

cert-manager automates TLS certificate issuance and renewal inside Kubernetes.

What It Does

  • Watches Ingress resources annotated with cert-manager.io/cluster-issuer
  • Automatically provisions TLS certificates from the configured issuer
  • Renews certificates before expiry (no manual rotation needed)
  • Stores certificates as Kubernetes Secret objects

Local CA Setup

For local development we use a self-signed CA chain (no internet access required):

graph TD
    SI["selfsigned-issuer\n(cert-manager built-in)"]
    CA["local-ca Certificate\n(stored in cert-manager/local-ca-key-pair Secret)"]
    LCI["local-ca-issuer\n(ClusterIssuer — use this in apps)"]
    CERT["*.local Certificate\n(issued per Ingress)"]

    SI -->|"signs"| CA
    CA -->|"backs"| LCI
    LCI -->|"issues"| CERT

Files:

  • infrastructure/controllers/cert-manager.yaml — HelmRelease
  • infrastructure/configs/cluster-issuer.yaml — ClusterIssuer + CA Certificate

Using TLS in an Ingress

Annotate any Ingress with:

annotations:
  cert-manager.io/cluster-issuer: "local-ca-issuer"
spec:
  tls:
    - hosts:
        - myapp.local
      secretName: myapp-tls

cert-manager will create myapp-tls Secret automatically.

Trust the Local CA (optional)

Browsers show "Not trusted" for self-signed certs. To fix:

# Export CA cert
kubectl get secret local-ca-key-pair -n cert-manager \
  -o jsonpath='{.data.tls\.crt}' | base64 -d > local-ca.crt

# Add to macOS Keychain as trusted
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain local-ca.crt

Key Configuration Decisions

Setting Value Why
crds.enabled: true true v1.15+ requires this to bundle CRDs into chart output
startupapicheck.enabled false Post-install Job is flaky on local clusters; main pods are healthy
Resources Minimal requests Conserve MacBook RAM

See ADR-006 for the full decision record.