fix(app): ensureHTTPApp must not strict-decode interface-typed routes - #157
Merged
Conversation
ensureHTTPApp used to decode the GET /config/apps/http response into a typed CaddyHTTPApp. That type transitively contains []CaddyHandler — an interface slice — which encoding/json cannot unmarshal into. On every daemon startup where Caddy already had a non-empty http app, the decode errored out, the code fell through to createHTTPApp, the PUT 409'd because the http app already existed, and the daemon logged a warning and silently lost every subsequent Caddy update that depended on EnsureServerConfig having succeeded. Symptom in the wild: registering a tunnel-promoted pool primary added the backend to /v1/backends but the corresponding TLS subject + srv0 route were never installed, so the new pool's HTTPS endpoint failed the TLS handshake. Restarting the daemon didn't recover, because the bug fires on every startup. Fix: probe with map[string]json.RawMessage on `servers` instead of the strict typed decode. Adds a regression test that asserts no spurious PUT is issued when an existing http app has handler-shaped routes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 13, 2026
pull Bot
referenced
this pull request
in Spencerx/Containarium
May 13, 2026
Ships the ensureHTTPApp interface-decode fix (#157) so the daemon can reapply Caddy state on every startup — required for tunnel-promoted pool primaries to register their TLS subject + srv0 route. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull Bot
referenced
this pull request
in Spencerx/Containarium
May 13, 2026
…e failures Captures two failure modes discovered while bringing up the `lab` pool against the prod sentinel on 2026-05-13: 1. PROXY v2 framing mismatch when the primary daemon isn't started with `--proxy-protocol`. The sentinel writes a PROXY v2 frame before the TLS bytes (when its own `--proxy-protocol` is on); the primary's Caddy interprets the frame as TLS garbage and the handshake fails silently — neither side logs anything useful, and probing Caddy locally at 127.0.0.1:443 succeeds, which is what makes the trap confusing. Fix is the matching `--proxy-protocol --proxy-protocol-trusted=127.0.0.0/8` on the primary. 2. `ensureHTTPApp` interface-decode bug pre-v0.16.6 (#157), which showed up as a `Failed to ensure Caddy server config: ... 409 key already exists: http` warning on every daemon startup with an existing Caddy http app, and silently lost subsequent Caddy updates. Fixed by upgrade. Also adds a cross-reference in `MULTI-POOL.md`'s "adding a new pool" workflow so the matching `--proxy-protocol` flag lands in the canonical runbook, not just in this troubleshooting section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ensureHTTPAppstrict-decoded the Caddy/config/apps/httpresponse into the typedCaddyHTTPApp. That type transitively containsHandle []CaddyHandler— an interface slice — whichencoding/jsoncannot unmarshal into. On every daemon startup where Caddy already had a non-empty http app, the decode errored out, the code fell through tocreateHTTPApp's PUT, and Caddy returned409 key already exists: http.EnsureServerConfighaving succeeded was silently lost.tunnel-lab-primary-1healthy in/v1/backends) but the new pool's TLS subject +srv0route never landed, so its HTTPS endpoint failed the TLS handshake. Restarting the daemon did not recover, because the bug fires on every startup.Fix: probe with
map[string]json.RawMessageonserversrather than the strict typed decode. The path that actually mutates Caddy already uses untyped maps viagetFullConfig/loadConfig, so we're just bringing the read path into alignment.Added a regression test
TestProxyManager_EnsureHTTPApp_AcceptsExistingConfigWithHandlersthat fails on the old code (asserts no PUT is issued to/config/apps/httpwhen the response contains a typedreverse_proxyhandler).Test plan
go test ./internal/app/ -run TestProxyManager -count=1 -v— all proxy tests pass including the new regressionFailed to ensure Caddy server config: ... status 409warning in observed prod logscontainarium daemononcontainarium-jump-usw1-sentineland verifycontainarium-lab.kafeido.appHTTPS returns the expected 404 (daemon's passthrough) instead of TLS handshake failure