v0.320.0: FileBrowser is part of the box again; every app says where its login is; a „Fájlok" button
gates / gates (push) Successful in 50s

FileBrowser (and traefik, cloudflared, samba) has no app.yaml, so Deployed is false. Since v0.315.0 the
app page read Deployed alone and showed FileBrowser "not installed", with Install and without its login.
A protected infra stack is now installed by definition on the app page (Deployed || Protected, as every
other surface already counted): settings/guide/log tabs, Restart only, no install page, no data tab.
The Install press would have deployed the infra stack as an app: DeployStack and the deploy API now
refuse a protected stack.

In the operator state (the box does not know FileBrowser's password - both demo boxes) the login panel
offers "Új jelszó beállítása": the file browser's own CLI with the server stopped (spiked on demo-hp:
new 200, old 401, users/shares/settings unchanged), verified, stored encrypted, state generated.

Every installed app's settings tab has the login panel with exactly one answer: the box's fields, the
login the app wrote (InitialCreds), or a sentence chosen by the catalog's new app_info.login_kind
(first_visit default, email, none; none behind the family gate says the family sign-in is the login).

"Fájlok ↗" opens the library folder, else the first declared folder, else a media app's first present
drive's media folder. The data tab lists each drive's media folders; a folder whose drive is not bound
into FileBrowser is text, never a link.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-16 15:19:14 +02:00
parent 39bf56298d
commit f30a80841e
59 changed files with 5669 additions and 104 deletions
+14 -1
View File
@@ -371,6 +371,19 @@ the install page's form groups use the same panel rule. **A login field the box
eye** — the page and the reveal endpoint share `storedValuePresent`. Design: felhom.eu `architecture/02-controller-module-map.md`
„The app page's layout".
**Logins and folders (v0.320.0).** *A protected infra stack is installed by definition* (FileBrowser, traefik,
cloudflared, samba — no app.yaml, so `Deployed` is false): settings, guide and log tabs only, Restart only, no install
page and no data tab (both 302 to the page), the curated name (`inframeta.go`). *Every installed app has „Belépés az
alkalmazásba" with exactly ONE answer* (`app_login.go` `loginAnswerFor`): the box's login fields · the login the app
wrote or FileBrowser's (`InitialCreds`) · a sentence from the catalog's `app_info.login_kind` (`first_visit` default,
`email`, `none`; `none` behind `family_gate` says the family sign-in is the login). FileBrowser in the `operator` state
(the box does not know its password) offers „Új jelszó beállítása": `POST /apps/filebrowser/initial-credentials/reset`
→ `stacks.ResetFileBrowserAdminPassword` (stop, the file browser's own CLI `set -u`, start, verify new=200 and
admin/admin refused, store encrypted, state `generated`). *„Fájlok ↗"* in the header opens the library folder, else
the first declared folder, else a media app's first present drive's `media` folder (`datapath_card.go`
`filesButtonLink`); the data tab lists each drive's media folders, and a folder whose drive is not bound into
FileBrowser is text, never a link.
#### „Még egy lépés" — a value asked AFTER the app starts (v0.315.0)
Some values can only be given once the app runs: Plex's claim code is minted on plex.tv and handed to a server that is
@@ -1076,7 +1089,7 @@ cloudflared is only deployed when a tunnel token is configured. **Triggers**: a
> **Mount prerequisite (Section-G):** the controller writes these stacks under `/opt/docker/stacks` *inside its container*, but `docker compose up` runs on the **guest** Docker daemon. The golden's controller-bootstrap (`felhom-agent` `build-golden.sh`) therefore bind-mounts that path **same-path** (`-v /opt/docker/stacks:/opt/docker/stacks`) so the daemon resolves every relative bind source — without it, all bind-mounted stacks (base infra and customer apps) silently break.
**FileBrowser admin password (v0.243.0, R-513).** FileBrowser used to accept `admin`/`admin` on every box. After `ensureFileBrowser`, every tick until decided, `Manager.EnsureFileBrowserAdminPassword` (`internal/stacks/filebrowser_password.go`) probes `http://filebrowser:80/api/auth/login` with admin/admin: **200** → a generated `password:16` is set through FileBrowser's API (never the `auth.adminPassword` config key — measured to overwrite a hand-set password on every start), verified both ways, and stored AES-encrypted in `settings.json` (`filebrowser_admin_state: generated`); **401** → `operator`, never touched. The FileBrowser app page shows user `admin` and the password behind the R-254 reveal (`POST /apps/filebrowser/initial-credentials/reveal`), or „az üzemeltető állította be".
**FileBrowser admin password (v0.243.0, R-513).** FileBrowser used to accept `admin`/`admin` on every box. After `ensureFileBrowser`, every tick until decided, `Manager.EnsureFileBrowserAdminPassword` (`internal/stacks/filebrowser_password.go`) probes `http://filebrowser:80/api/auth/login` with admin/admin: **200** → a generated `password:16` is set through FileBrowser's API (never the `auth.adminPassword` config key — measured to overwrite a hand-set password on every start), verified both ways, and stored AES-encrypted in `settings.json` (`filebrowser_admin_state: generated`); **401** → `operator`, never touched. The FileBrowser app page shows user `admin` and the password behind the R-254 reveal (`POST /apps/filebrowser/initial-credentials/reveal`), or — `operator` — „Ezt a jelszót te állítottad be…" with „Új jelszó beállítása" (v0.320.0, the file browser's CLI with the server stopped; the `auth.adminPassword` key / `FILEBROWSER_ADMIN_PASSWORD` env re-apply on every start and are still never used).
**Controller routing + the wildcard cert anchor (`wireController` → `RenderControllerRoute`, v0.41.1 / v0.42.1).** filebrowser self-registers with traefik via Docker labels + `traefik-public` membership baked into its compose; the controller can't (it's started by the golden bootstrap *before* `traefik-public` exists, and the v2 `bootstrap.json` carries no domain — that comes from the hub pull). So `EnsureBaseStack` wires the controller **post-pull**: it `docker network connect traefik-public felhom-controller` and writes a traefik file-provider route `dynamic/controller.yml` (`Host(felhom.<domain>) → http://felhom-controller:8080`, write-if-changed). When DNS-01 ACME is configured, that route is **also the wildcard-cert anchor**: its router-level `tls.domains: *.<domain>` makes traefik **proactively obtain the wildcard `*.<domain>` + apex via Cloudflare DNS-01 at startup** (an entrypoint-level `http.tls.domains` does *not* trigger issuance in traefik v3 — only a router-level `tls.domains` does). Every other router then serves that one real wildcard cert by SNI — no per-app `certresolver` labels. This is what lets a LAN client reach the box directly at `*.<domain>` with the real cert (the `felhom-agent` split-horizon resolver depends on it).