From 886f596393caf4665d365027967c22b634a7e40b Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Fri, 26 Jun 2026 11:29:04 +0200 Subject: [PATCH] docs: REPORT for crafty seeded admin password (gokapi pattern); live-verified fresh install + API login --- REPORT.md | 94 +++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/REPORT.md b/REPORT.md index 8a7a23b..63190b8 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,59 +1,51 @@ -# REPORT — crafty-controller healthcheck fix +# REPORT — crafty-controller: seed a felhom-generated admin password (gokapi pattern) -**Date:** 2026-06-26 · **Repo:** `app-catalog-felhom.eu` (catalog-only) · **Commit:** `68ce009` -**Guest:** 9201 (`demo-felhom`) on `felhom-pve` · **Controller:** v0.82.0 (unchanged) +**Date:** 2026-06-26 · **Repo:** `app-catalog-felhom.eu` (catalog-only) · **Commit:** `5a403d1` +**Guest:** 9201 (`demo-felhom`) on `felhom-pve` · **Controller:** v0.84.0 (unchanged — reuses its `initial_credentials` reader) -## Scope -Catalog-only fix of the crafty-controller healthcheck (no Go change, no controller/agent rebuild, no -version bump). Built on the prior diagnosis (root cause: image has no `curl`). +## Goal +Replace Crafty's auto-generated, ugly random admin password with a clean **felhom-generated** one, +using the same seeding pattern as gokapi (consistency), while keeping it visible on the app page. -## Files changed (2) -- `templates/crafty-controller/docker-compose.yml` — Docker healthcheck `test` `curl` → python3 TLS - socket probe; `start_period` 30s → 60s. -- `templates/crafty-controller/.felhom.yml` — controller-side probe `type: http` → `type: tcp` (8443 - is TLS-only). +## Root mechanism (discovered in Crafty source) +`main_models.default_settings` reads `app/config/default.json` on fresh install; the image ships +`config_original/default.json = {"username":"admin","password":"crafty"}` — 6 chars, below Crafty's +8-char minimum, so Crafty rejected it and generated a random password into `default-creds.txt`. We can't +"lengthen" that internal fallback — we **seed** a valid `default.json` instead. -Effective new Docker healthcheck: -``` -["CMD","/usr/bin/python3","-c","import socket,ssl; ssl._create_unverified_context().wrap_socket(socket.create_connection(('127.0.0.1',8443),timeout=3)).close()"] -interval 30s · timeout 5s · retries 3 · start_period 60s -``` +## Change (catalog-only) +- **`docker-compose.yml`**: new `CRAFTY_PASSWORD` env + an **entrypoint** wrapper that overwrites + `config_original/default.json` with `{"username":"admin","password":"$CRAFTY_PASSWORD"}` before exec'ing + the image launcher (`/crafty/docker_launcher.sh -d -i`). On fresh install the launcher copies our + template into the config volume → Crafty creates `admin` with our password. +- **`.felhom.yml`**: new `CRAFTY_PASSWORD` deploy field (`type: password`, `generate: password:24`, + `locked_after_deploy` — mirrors gokapi's `GOKAPI_PASSWORD`, alphanumeric so JSON/shell-safe). Repointed + `initial_credentials.file` `default-creds.txt` → `default.json` so the controller's "Kezdeti belépési + adatok" card shows the **seeded** password. +- No controller change: the deploy flow already injects/decrypts password deploy-fields into the compose + env (`stackEnv`), and v0.84.0's `initial_credentials` reader already parses `default.json`. -## Two root causes (both required) -1. **Docker probe** used `curl`, absent in `crafty-4:4.4.8` (`exec: "curl": not found`, FailingStreak 150). -2. **Controller-side probe** did plaintext `http://…:8443` against a TLS port → `HealthProbe.Healthy=false` - → `manager.go:471` overrides `running` back to `unhealthy`. Fixing only #1 would have flipped back at - the next controller probe. Verified empirically. +## Live validation (guest 9201 — fresh install via the real pipeline) +Removed crafty + wiped its volumes, then deployed via `POST /api/stacks/crafty-controller/deploy` with +`{DOMAIN, SUBDOMAIN, CRAFTY_PASSWORD}` (clean 24-char alphanumeric). -## Deploy path (real flow) -1. Commit + push to `main` (`68ce009`). -2. Controller git-sync via `POST /api/sync` (Host: felhom.demo-felhom.eu) → `[sync] Updated - crafty-controller/docker-compose.yml` + `.felhom.yml`; `app.yaml` untouched. -3. Recreate via the UI update path `POST /api/stacks/crafty-controller/update` (`docker compose up -d`; - restart would not pick up a healthcheck change). +| Check | Result | +|---|---| +| Fresh install, **no "Default password too short"** | ✅ Crafty used our seeded password | +| `default.json` in volume | `{"username":"admin","password":""}` | +| **Crafty API login** `admin`/seeded | **HTTP 200 + token** (gold standard) | +| Stray `default-creds.txt` random pw | **401 rejected** — non-functional artifact (see note) | +| `app.yaml` | `CRAFTY_PASSWORD: ENC:…` (encrypted at rest) + in `locked_fields` | +| App-page card | shows the seeded password (from `default.json`) | +| Public URL `minecraft.demo-felhom.eu` | **302** | -## Verification (acceptance gate) -- **New healthcheck live:** `docker inspect .Config.Healthcheck` = python3 cmd, `StartPeriod` 60s. -- **Executes + passes:** `State.Health` → `Status: healthy`, `FailingStreak: 0`, Log `ExitCode: 0`. -- **Controller-side probe clear:** `GET /api/stacks/crafty-controller` → `health_probe.healthy: true`, - `details: [{type: tcp, target: :8443, healthy: true, latency: 5ms}]`; http-vs-TLS `[WARN] Health probe - crafty-controller …` entries stopped at the 07:46 sync, none after. -- **Green + stable:** `Up 3 minutes (healthy)`, state `running` across a probe cycle (override gone). -- **Route un-withheld:** Traefik now publishes `crafty-controller@docker` (in its access log) — the - `routeUnpublished` / "URL nem elérhető" condition is resolved. +## Known quirk (documented, low-risk) +Crafty still writes `default-creds.txt` with a *different* random password during init even though it +used our `default.json`. That password is **non-functional** (login → 401) and the file is **not** shown +anywhere in the felhom UI (the card reads `default.json`; FileBrowser is scoped to userdata, not +`/crafty/app/config`). Left as-is — a post-boot cleanup would be a racy entrypoint hack for an invisible +file. The canonical, working password is the seeded one shown on the app page. -## Open item (separate task — NOT this fix) -Public URL `https://minecraft.demo-felhom.eu` still returns **502**. Distinct, pre-existing bug exposed -by the now-published route: Traefik proxies `http://172.18.0.6:8443` to Crafty's **HTTPS-only** -self-signed backend (access log: `502 … "crafty-controller@docker" "http://172.18.0.6:8443"`). Crafty -serves no plain-HTTP port (only 8443 listens). A working fix needs Traefik HTTPS backend -(`scheme=https`) **plus** a `serversTransport` with `insecureSkipVerify` for the self-signed cert — -the latter cannot be set via Docker labels in Traefik v3, so it requires the controller-generated -Traefik config / felhom-controller Go (out of this catalog-only task). Investigation of fix options is -in progress per request; plan to follow before any implementation. - -## Observations (documented, not acted on) -1. `probeHTTP` can only target `http://` backends — no TLS support. A general fix would teach it - `https`/honor a `scheme` field so future TLS apps can use `type: http`/`api` checks. Own task. -2. Catalog-wide audit: other apps whose Docker healthcheck uses a possibly-absent binary - (`curl`/`wget`), or whose `.felhom.yml` uses `type: http` against a TLS port. Own task. +## Consistency +crafty now matches gokapi: a felhom-generated, locked, `password`-type deploy field set at deploy time — +plus the app-page card (v0.84.0 reader) so the initial login is also visible there.