docs(files): record the general.host trap + that a green monitor proves nothing

Propagate the bare-hostname fix (10b86ae) to the docs that still said "three
traps", and write down the meta-lesson it exposed.

The bug was invisible to every check we had: Filestash strips the scheme
before its own Host check, so `curl /` returned 200, the API answered, wrong
passwords were rejected, and the brand-new Uptime Kuma HTTP monitor stayed
green — while the SPA computed `http://https://files...` and no browser could
use the site. An HTTP monitor asserts "server returned 200", which is a much
weaker claim than "the app works".

- CLAUDE.md / README: four traps now, host-scheme first; add the post-change
  check (`/api/config` → origin must be the real https URL).
- 19-routes: login form only renders at ?action=redirect (a bare 303 is
  normal, not a bug); assert origin after config changes.
- 10-uptime-kuma: an HTTP monitor cannot see an SPA break — use a Keyword
  monitor if you want teeth, and don't read green as "users can log in".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 18:31:46 +02:00
parent 10b86ae23e
commit 08fe8c9c53
4 changed files with 44 additions and 6 deletions

View File

@@ -181,8 +181,13 @@ Full design, deploy steps and gotchas: **`plan/20-files.md`**. The short version
Only valid once the host is off the public internet: an unauthenticated
*writable* share on a public domain is an open upload relay.
Three traps that cost real time (all enforced or documented in the tooling):
Four traps that cost real time (all enforced or documented in the tooling):
- **`general.host` is a bare hostname**, no scheme (`files.${BASE_DOMAIN}`), with
`force_ssl: true`. The SPA builds its redirect origin as `scheme + host`, so a
URL there produces `http://https://files...` and every client-side redirect
breaks. The server strips the scheme before its *own* Host check, so `curl`
and the uptime monitor stay **green while every browser is broken**.
- **`FILES_PASSWORD_HASH` must be `$6$`** (`openssl passwd -6`). The htpasswd
plugin's bcrypt branch only matches `$2a$`, so a `$2y$` hash from
`htpasswd -B` fails *every* login, silently. `render-config.sh` rejects it.
@@ -192,6 +197,11 @@ Three traps that cost real time (all enforced or documented in the tooling):
- **Don't set `APPLICATION_URL`/`ADMIN_PASSWORD` env** — either makes Filestash
rewrite `config.json` at boot, which fails against the `:ro` mount.
> Verifying this service: a 200 on `/` only proves the server is up. Check the
> browser-facing origin — `curl -s -H 'X-Requested-With: XmlHttpRequest`
> `https://files.${BASE_DOMAIN}/api/config | jq -r .result.origin` must print
> `https://files.${BASE_DOMAIN}` — and re-read `docker compose logs filestash`.
## Join (guests)
1. Open `https://${BASE_DOMAIN}`, download FjordLauncherUnlocked for your OS.