github doctor-io/homeio v1.9.2
Homeio v1.9.2

latest release: v1.9.3
7 hours ago

Fixes #37 — a user locked out of his own server on the registration page, on an install that already had an account.

What happened

The proxy set no Cache-Control on its own responses. A tunnel or CDN in front, configured to cache aggressively, was therefore free to keep them — including the 307 -> /register an install answers while it is still empty. Once that redirect sat in the edge cache, every later visitor was sent to registration however many accounts existed, and an authenticated one had their session cookie cleared on the way back.

The reporter had ruled out caching because incognito, a different browser and a different device all behaved identically. That is the detail that identifies it rather than excluding it: nothing client-side survives all three, but a cache upstream of all three does. Our own documentation recommends putting Homeio behind exactly such a tunnel.

A second fault turned any transient blip into the same lockout. A failed "are there any accounts" lookup returned false, which does not mean "lookup failed" — it means "fresh install, nobody is registered". So a momentary database or network hiccup signed everyone out and offered the machine up for registration.

The fix

  • Every non-static response now carries private, no-store. Immutable assets never reach that middleware — _next/static is excluded by the matcher — so they keep the long-lived caching that is the point of a CDN.
  • Not knowing now answers "accounts exist". A genuinely fresh install pays one redirect to /login; the old answer cost a running install its sessions.
  • Backported alongside: container logs had their ANSI escapes printed as literal [36m noise, and \x1b[33mWARN: leaves no word boundary before WARN, so every warning was labelled a red error.

Both proxy changes already shipped on the v2.0 line. This brings them to 1.9 so people on the released version get them without waiting.

Why our testing missed it

Worth recording, because the gap was in the method rather than the code.

Every check that shipped 1.9.1 went straight to the origin — 127.0.0.1:12026 or the LAN address — so the cache that causes this was never in the path. The proxy's own test asserted the defective behaviour as intended (falls back to register when auth status lookup fails), which also made it count as covered. And no test inspected response headers at all: six headers.get calls across the suite, four on location, two on x-auth-entry, none on Cache-Control.

The test that codified the old behaviour has been inverted, with a comment saying why, and there are now tests asserting the cache headers on both a dynamic response and an immutable asset.

Verification

  • 835 tests across 190 files, all passing.
  • Built the image and ran it: a fresh container with no account answers 307 -> /register carrying private, no-store, /register carries it too, and an immutable asset still answers public, max-age=31536000, immutable.
  • Confirmed on the live server through its public hostname that the v2.0 form of this fix produces cf-cache-status: BYPASS at Cloudflare's edge.

Don't miss a new homeio release

NewReleases is sending notifications on new releases.