https only (R-1033, P1): controller v0.312.0 proven on Tester 1, demo-hp, demo-felhom (29 names); scripts/https_only_check.py; 01/13/poster facts; decision 246 (decided by CC unattended); R-1033 P1 narrowed; R-1041..R-1043
gates / gates (push) Successful in 6m34s
gates / gates (push) Successful in 6m34s
This commit is contained in:
@@ -139,6 +139,19 @@ read the LEFTMOST entry have the chain removed on their router. Design and measu
|
||||
MeTube) was SPIKED on this base and passed (`audits/permanent-gate-2026-10-01/VERDICT.md`) and is BUILT since
|
||||
controller 0.287.0 (`09` §3 decision 64) — the family gate, at the end of this section.
|
||||
|
||||
**Every public name answers only over https (recorded 2026-10-14, R-1033 — P1 by the operator, `09` §3 decision 244;
|
||||
controller ≥ 0.312.0).** A visitor who types `http://` reaches Cloudflare over plain http; the tunnel still delivers to
|
||||
traefik's :443 and says so in `X-Forwarded-Proto: http` (measured), which traefik keeps only from the tunnel's address.
|
||||
The first link of the entrypoint chain `felhom-forwarded` (`felhom-https-only`) answers it with a 301 to the same https
|
||||
URL, path and query kept, BEFORE any app sees the request — so a login page is never served, and a password never sent,
|
||||
over http. A name with no app route is redirected by a priority-1 catch-all that matches only `X-Forwarded-Proto: http`.
|
||||
HSTS: one day, no subdomains, no preload (a longer value is the operator's decision). **Where it is enforced:** on the box
|
||||
(`dynamic/forwarded.yml`, rewritten on every health tick if it drifts), not at Cloudflare: the boxes' Cloudflare keys
|
||||
cannot change zone settings (403, measured on every zone) — Cloudflare's „Always Use HTTPS" is the operator's optional
|
||||
second layer. **How it is checked:** `scripts/https_only_check.py` lists every public name from the box's own traefik
|
||||
routes and demands 301/308 to the same https URL (negative control: a stub answering plain 200 must be convicted).
|
||||
Evidence: `audits/https-only-2026-10-14/`.
|
||||
|
||||
**Who may reach an app, and through what (recorded 2026-09-29 — no document said it before; spike finding F1).**
|
||||
Every app is reached only through the box's traefik (no catalog app publishes a host port except crafty-controller's
|
||||
game ports; none uses host networking — read from the catalog 2026-09-29). traefik routes by host name: the tunnel's
|
||||
|
||||
@@ -922,6 +922,15 @@ its length, and both fixes cost something the household would notice — operato
|
||||
245. **Drive events = option A.** On a drive added, removed or back, the box restarts the media apps; it makes a new
|
||||
drive ready inside each media app; it pauses torrents before a safe removal; and it adds guards only where a
|
||||
measurement shows loss. *Operator ruling 2026-10-14 22:13.* (R-1023; `15-media-library.md` §10)
|
||||
246. **Where https-only is enforced: on the box (traefik), not at Cloudflare.** *Decided by CC unattended 2026-10-14
|
||||
22:40 — operator may reverse.* Question: which switch makes every public name answer only over https tonight?
|
||||
Options: (a) Cloudflare „Always Use HTTPS" + HSTS per zone — one switch per zone, nothing on the box can forget it,
|
||||
but every box's `cf_api_token` lacks „Zone Settings" (403 on all three zones, measured) and no account key is
|
||||
stored: costs a key change per customer first; (b) traefik on the box redirects when the trusted tunnel says
|
||||
`X-Forwarded-Proto: http` — needs a controller release (v0.312.0), reaches a box with the floor, and is rewritten
|
||||
on drift every health tick; (c) a Cloudflare firewall rule (the keys CAN edit those) — it can only BLOCK, which
|
||||
breaks Sonarr's login (its own `http://` redirect). Chosen (b): it works with the keys we have, was measured
|
||||
(bench + three zones), and leaves (a) open as a second layer once the operator widens the keys (R-1042).
|
||||
|
||||
### 2026-10-14 (evening, ~21:20) — the media folders and the N100 (recorded before the work; the media-folder-fix brief)
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ OS packages (exact versions, apt-signed), the installer script (by tag, R-980).
|
||||
| boundary | verdict | evidence |
|
||||
|---|---|---|
|
||||
| end-user ↔ apps | holds, with gaps | traefik routing and header stripping hold; homepage has the Docker socket and no gate (R-981) |
|
||||
| **added 2026-10-14 (R-1033, P1):** a visitor ↔ Cloudflare over plain http | holds on boxes with controller ≥ 0.312.0 | before: every public name answered `http://` (login pages too), and Sonarr/Radarr/Prowlarr redirected https visitors to an absolute `http://` login; a password could cross an untrusted network unencrypted (attacker: anyone on the visitor's network). Now traefik sends every `http://` request to https (301) before an app sees it, HSTS one day; boxes below 0.312.0 (Tester 2 at 0.292.0) keep the gap until the floor delivers it. `audits/https-only-2026-10-14/` |
|
||||
| customer ↔ controller UI | partly | bcrypt and session hold; small gaps (R-983); family sessions survive a reset (R-976) |
|
||||
| controller ↔ agent | partly | every route bound to the caller's guest; a compromised controller can still flush restore points (R-973), void the recovery code (R-978), and — since agent v0.155.0 — switch the whole machine off once per power-on, holding the hub's silence alarms for up to 14 days (R-998; mitigations and residual risk: `14-host-power-off.md` §5) |
|
||||
| **added (R-1007):** controller → an app's own job queue | holds — nothing new | the `after_unclean_boot` commands run inside the app's container through the docker socket the controller already holds, and read the app's database with a read-only session: no key into the household's account, nothing a compromised controller could not already do (exec in any app, read its database). The household's lost-file names stay on the box (`app.yaml`, the app page); the operator event carries counts only, and a failing command's output is never logged (security review of controller `8d862e4`, fixed in `3b85a0c`) |
|
||||
|
||||
@@ -69,7 +69,7 @@ Inside, from bottom to top:
|
||||
Note on the drawing: the data drives are attached to the guest from the host; the **whole-guest backups do not include the data drives** (that is what the per-app tiers are for).
|
||||
|
||||
Arrows out of the box:
|
||||
- **Household's phone / laptop → Cloudflare → cloudflared → Traefik → app** (solid, green). Label: "Remote access. HTTPS ends at Cloudflare's edge, so Cloudflare could technically see this traffic (later item: our own relay)." Also a short local arrow: "At home on the LAN: direct to Traefik."
|
||||
- **Household's phone / laptop → Cloudflare → cloudflared → Traefik → app** (solid, green). Label: "Remote access. HTTPS ends at Cloudflare's edge, so Cloudflare could technically see this traffic (later item: our own relay)." **Since 2026-10-14 (R-1033): https only** — a visitor who types `http://` is sent to `https://` by Traefik before any app answers (HSTS one day). Also a short local arrow: "At home on the LAN: direct to Traefik."
|
||||
- **Box → hub** (dotted): "Reports every few minutes; asks for signed jobs. The hub never connects into a box."
|
||||
- **Box → ep0** (dashed, through a small padlock tunnel labelled **WireGuard**): "Whole-guest backup, encrypted on the box, sent through WireGuard." — *fix (b), 2026-10-09: the label must name BOTH, because "encrypted on the box" alone read as if WireGuard were doing the encrypting.*
|
||||
- **Box → Hetzner Storage Box** (dashed): "Per-app off-site backup (restic), encrypted on the box. The box's key can only ADD copies; old copies are removed only in a weekly clean-up window the hub opens."
|
||||
|
||||
Reference in New Issue
Block a user