Files
felhom-controller/REPORT.md
T
2026-06-11 18:30:42 +02:00

47 lines
3.3 KiB
Markdown

# REPORT — v0.42.1: real Let's Encrypt wildcard cert (wildcard proactive issuance)
**Repo:** `felhom-controller` · **Version:** 0.42.1 · **Date:** 2026-06-11
**Pushed commits:** `84c3e84` (v0.42.0, superseded) → `e61e7dd` (v0.42.1) · paired with `felhom-agent`
v0.21.0 (split-horizon LAN resolver — depends on this real cert) + golden rebake (controller 0.42.1).
## What shipped
The base-infra traefik obtained **no** real cert (acme.json empty) — both routers relied on the
websecure entrypoint-default `certResolver`, which does **not** trigger proactive DNS-01 issuance, so
everything ran on traefik's self-signed default (masked externally only by the tunnel's `noTLSVerify`).
This blocked LAN-direct (a LAN client TLS-handshakes straight to traefik and needs the real cert).
- **`infra.RenderControllerRoute(domain, wildcardTLS)`** — the always-present controller route is now
the **wildcard-issuance anchor**: when DNS-01 ACME is configured (`CFAPIToken && Email`) it carries
router-level `tls.certResolver: letsencrypt` + `tls.domains: [{main: "*.<domain>", sans: ["<domain>"]}]`,
so traefik **proactively obtains `*.<domain>` + apex at startup** via Cloudflare DNS-01. Every other
router (filebrowser, future apps) then serves that one wildcard by SNI match — **no per-app
certresolver labels**, real cert ready before the first client connects. `stacks.wireController` passes
`wildcardTLS = (CFAPIToken != "" && Email != "")`.
- **Key empirical finding (staging on 9201):** traefik v3 issues a cert from a **router-level**
`tls.domains` but **NOT** from the entrypoint-level `http.tls.domains` (acme.json stayed 0 bytes with
the latter). v0.42.0's entrypoint-domains attempt + `TraefikData.Domain` was reverted.
## Validation (staging → prod on guest 9201)
- **CF token pre-check:** active, scoped to `demo-felhom.eu`, DNS read OK (DNS:Edit confirmed by the run).
- **Staging (Fake LE):** with the router-level wildcard, acme.json went 0 → populated; `felhom.*`,
`files.*`, and arbitrary `anything.demo-felhom.eu` all presented `*.demo-felhom.eu` (issuer `(STAGING)`)
— one wildcard, zero per-app labels.
- **Prod switch:** wiped acme.json, clean first-boot render (no `caServer`, no entrypoint domains) →
PROD wildcard issued (acme.json ~16 KB).
- **GATE (from dooplex, real LAN host, direct to guest IP):** `felhom.demo-felhom.eu` + `files.demo-felhom.eu`
**`200 ssl_verify=0`**; issuer **`C=US, O=Let's Encrypt, CN=YR1`** (real prod LE); subject
`CN=*.demo-felhom.eu`, SAN `*.demo-felhom.eu, demo-felhom.eu`. Dashboard title `Vezérlőpult — Felhom.eu`.
## Live deploy
- Built + pushed `0.42.1`; deployed to 9201 (clean first-boot: wipe acme.json → controller renders prod
traefik.yml + wildcard route → traefik obtains the prod wildcard).
- **Golden rebaked** with controller 0.42.1 → `local:backup/vzdump-lxc-9100-2026_06_11-18_10_11.tar.zst`
(fresh provisions get a real wildcard cert on first boot).
## Notes
- The traefik **dashboard route** (`dynamic/dashboard.yml`) remains deferred (needs a generated
basic-auth hash) — routing/cert for filebrowser + controller work without it.
- HTTP-01 path (ACME email but no CF token) can't issue wildcards → falls back to a plain TLS route
(self-signed). The felhom production always uses Cloudflare DNS-01, so the wildcard path is the norm.