Files
dezky/infrastructure/production/fleet/cert-manager
Ronni Baslund e77a963390
ci / changes (push) Successful in 3s
ci / tc_portal (push) Has been skipped
ci / tc_booking (push) Has been skipped
ci / tc_operator (push) Has been skipped
ci / tc_platform_api (push) Has been skipped
ci / tc_website (push) Has been skipped
ci / build_portal (push) Has been skipped
ci / test_platform_api (push) Has been skipped
ci / build_booking (push) Has been skipped
ci / build_operator (push) Has been skipped
ci / build_platform_api (push) Has been skipped
ci / deploy (push) Has been skipped
feat(infra): real TLS for mail.dezky.eu
The cert-sync timer waited forever for a mail/mail-tls secret no
Certificate resource ever requested — Stalwart served self-signed certs
since install, so mail clients refused the IMAP handshake ('cannot verify
account name or password' in Apple Mail). Adds the cert-manager
Certificate (HTTP-01 via Traefik on :80) and documents the v0.16 wrinkle:
TLS files aren't read from config anymore; a one-time file-backed
x:Certificate object (created via management JMAP) points at the synced
paths, after which cert-sync renewals keep working unchanged. Verified:
:993 now serves the Let's Encrypt cert, verify rc=0.
2026-06-10 21:58:35 +02:00
..

fleet/cert-manager — TLS for the cluster

cert-manager + ACME ClusterIssuers. Installs via the k3s built-in Helm controller (no Helm CLI needed), then defines letsencrypt-staging and letsencrypt-prod (HTTP-01 through the bundled Traefik).

Apply order (matters — issuers need the CRDs first)

# 1) Install cert-manager
kubectl apply -f cert-manager.yaml

# 2) Wait until it's up (CRDs + webhook ready)
kubectl -n cert-manager rollout status deploy/cert-manager-webhook --timeout=180s
kubectl -n cert-manager get pods

# 3) Create the issuers
kubectl apply -f cluster-issuer.yaml
kubectl get clusterissuer            # both should report READY=True

Notes

  • ACME email is info@dezky.eu — change in cluster-issuer.yaml if needed.
  • Test with letsencrypt-staging first (set an Ingress annotation cert-manager.io/cluster-issuer: letsencrypt-staging) to avoid burning the strict prod rate limits, then switch the apps to letsencrypt-prod.
  • HTTP-01 requires each hostname's DNS A record → 46.4.78.187 and port 80 open (already true). A cert won't issue until DNS resolves.
  • The app Ingresses (fleet/apps/) already reference letsencrypt-prod.