feat(k8s): terminate TLS in the cluster for a public domain (closes #177) #178

Open
not wants to merge 3 commits from feat/177-public-tls-edge into main
3 Commits
Author SHA1 Message Date
notandClaude Opus 5 399d110663 docs(arch): ADR-0035 and the runbook section for publishing the stack (refs #177)
CI / k8s (pull_request) Successful in 6s
CI / build (pull_request) Successful in 1m28s
CI / lint (pull_request) Successful in 1m51s
CI / unit (pull_request) Successful in 1m12s
CI / frontend (pull_request) Successful in 2m11s
CI / mutation (pull_request) Successful in 3m45s
CI / verify-stack (pull_request) Successful in 8m15s
The ADR records why the edge is in the cluster rather than on the Fedora host —
routing and certificates should be state a `helm upgrade` can see — and the
three costs that buys: the host forward nobody in the cluster can repair, the
Let's Encrypt rate limit that makes `persistence.storageClass` non-optional, and
publishing behandel and beheer to the internet behind synthetic accounts.

Runbook §10 is the operational half: the five DNS records, the two firewalld
rules (including the masquerade that makes the return path work), and the
symptoms each missing piece produces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 16:30:38 +02:00
notandClaude Opus 5 56cba9c340 feat(k8s): terminate TLS in the cluster for a public domain (refs #177)
`public.domain` is the whole switch. Empty — the default, and what compose, CI
and a laptop cluster use — renders nothing new and leaves every manifest as it
was. Set it and templates/edge.yaml adds a Caddy deployment that gets its own
certificates from Let's Encrypt and proxies the five browser-facing hostnames to
the ClusterIP services, so a public deployment doesn't use their NodePorts at
all.

Caddy rather than an ingress controller because the four portals already run
caddy:2-alpine (ADR-0034, whose ceiling note called exactly this out): no new
dependency, no cert-manager, no CRDs, no Ingress objects for five hostnames that
never change. The Fedora host keeps only a layer-4 forward of 80/443, because
the public IP is there and nothing in the cluster can claim it.

KC_HOSTNAME and the portals' config.json now both come from `big.keycloakUrl`,
so the issuer a token carries and the authority the BFF discovers are one string
by construction (ADR-0010) rather than by two templates agreeing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 16:30:38 +02:00
notandClaude Opus 5 88fda30008 test(k8s): pin the issuer, the portal authority and the public edge (refs #177)
Keycloak pins one issuer and each portal is configured with one authority; when
they drift the symptom lands three services away — a login that bounces back
logged out, or a 401 from the BFF (ADR-0010) — so assert they are the same
string. The same check states what publishing the stack has to mean: with
`public.domain` set the five hostnames are served and both halves become
`https://auth.<domain>`, and with it empty nothing of the edge renders, which is
what compose, CI and a laptop cluster depend on.

Red: the chart has no `public.domain`, so setting it changes nothing and no
hostname is published.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 16:30:38 +02:00