Document the Traefik label loss and certificate refresh

This commit is contained in:
2026-10-25 23:41:30 +08:00
parent 437a2e447e
commit f4a63c884f
2 changed files with 21 additions and 2 deletions
+13 -2
View File
@@ -96,7 +96,12 @@ what we take vs. skip). Never vendor it into the build.
*not* merge its generated Traefik labels for API-created apps: the full
label set must live in `custom_labels` (mirror a working app's generated
format — http/https routers with `certresolver=letsencrypt` — plus the TCP
passthrough lines). Deployment JSON from the API can break `jq` (invalid
passthrough lines). **On 2026-10-25 the TCP lines were found missing after a
deploy** (custom_labels held only HTTP/Caddy labels), so Traefik terminated
tunnel SNI with its default certificate. Restored with
`PATCH /api/v1/applications/{uuid}` (`custom_labels` only, current HTTP
labels preserved) and verified they survive a redeploy; check them after any
app update. Deployment JSON from the API can break `jq` (invalid
escapes in the logs field) — parse with python instead.
- **Deployment**: the multi-stage `Dockerfile` builds a static non-root
alpine image; verify `CGO_ENABLED=0 go build -trimpath -ldflags="-s -w"
@@ -123,7 +128,13 @@ what we take vs. skip). Never vendor it into the build.
`ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory`
for tests; staging certs are untrusted. Local ACME E2E is Pebble +
pebble-challtestsrv with `DNS_PROVIDER=challtestsrv` and
`ACME_CA_BUNDLE=.../test/certs/pebble.minica.pem`.
`ACME_CA_BUNDLE=.../test/certs/pebble.minica.pem`. The official CLI caches
its certificate and polls `GET /api/tunnel/{id}/certificate` every 12 hours
(every minute within 30 days of expiry), applying a renewed certificate to
new connections without disconnecting; after switching the issuer, restart
the service (`opentunnel down` / `up`) to fetch it immediately. An issuance
killed mid-flight can leave `_acme-challenge` TXT records behind; delete them
with `dns/deleteByNameType` (production and test tunnels share the zone).
- **macOS system curl (LibreSSL) does not send SNI for `*.localhost` names**,
so `curl https://api.<id>.localhost:8443/` gets closed (the relay requires
SNI). Test with `openssl s_client -servername ...` or Homebrew curl.