docs: CHANGELOG + REPORT for crafty 4.10.7 bump, port range, guidance; flag in-place-upgrade TOTP lockout

This commit is contained in:
2026-06-26 11:48:53 +02:00
parent 2d5b835636
commit 0012d66fc3
2 changed files with 65 additions and 44 deletions
+43 -44
View File
@@ -1,51 +1,50 @@
# REPORT — crafty-controller: seed a felhom-generated admin password (gokapi pattern)
# REPORT — crafty-controller: image bump 4.4.8→4.10.7 + Java game-port range + connection guidance
**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)
**Date:** 2026-06-26 · **Repo:** `app-catalog-felhom.eu` (catalog-only) · **Commit:** `2d5b835` (template)
**Guest:** 9201 (`demo-felhom`) on `felhom-pve` · **Controller:** unchanged
## 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.
## 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.
## 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`.
## 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).
## Changes (3, catalog-only)
- **A — image bump**: `crafty-4:4.4.8`**`4.10.7`** (confirmed latest stable in the GitLab registry;
4.10.8/4.11.0 do not exist). Security CVEs + Java.
- **B — publish game ports**: added `ports: ["25565-25575:25565-25575"]` (TCP, 11 Java servers). No
`network_mode: host`; Traefik labels + python3 healthcheck unchanged.
- **C — app-page guidance** (`.felhom.yml`): port-range usage + LAN connection (manual IP:port) +
internet/port-forward note, in `first_steps`/`prerequisites` (the only rendered AppInfo fields).
## Verification (live, guest 9201)
| Check | Result |
|---|---|
| Fresh install, **no "Default password too short"** | ✅ Crafty used our seeded password |
| `default.json` in volume | `{"username":"admin","password":"<seeded>"}` |
| **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** |
| Image + health | `crafty-4:4.10.7`, `Up (healthy)` (python3 TLS healthcheck passes) |
| Public URL | `minecraft.demo-felhom.eu`**302** (prior 502 fix holds) |
| **Java 25 present?** | **YES**`/usr/lib/jvm/java-25-openjdk-amd64`, default `java -version` = openjdk 25.0.3 (also 8/11/17/21). Latest-MC (26.x) blocker resolved. |
| Migration | clean from 4.4.8 — "Crafty has fully started"; no traceback (but see TOTP caveat) |
| Ports published | `0.0.0.0:25565-25575->25565-25575/tcp` (only host-bound range; others are image EXPOSEs) |
| **Guest network mode** | **bridged** (net0 → vmbr0), own LAN IP **192.168.0.121** (DHCP) — direct LAN reach, no host NAT forward |
| **LAN reachability** | from build server 192.168.0.180: `192.168.0.121:25565` **OPEN**, `:25575` **OPEN**; `:25600` (outside range) **closed** (negative control) |
| Fresh deploy login | admin / seeded pw → **200 + token** |
| App-page card + guidance | shows the seeded admin password; "25565" guidance rendered |
## 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.
Reachability used synthetic listeners on the range ends (the prior fresh-redeploy removed the old test
server). A real Minecraft-client join is the optional gold standard (not performed; Crafty's first server
binds `0.0.0.0:25565` by default).
## 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.
## ⚠ Key finding — in-place upgrade locks out the admin (TOTP)
An **in-place** 4.4.8→4.10.7 upgrade of the existing seeded install **locked out admin login** (401
`INCORRECT_CREDENTIALS`) **despite the correct password** (the stored argon2 hash verifies True). Root
cause: 4.10.7's login treats `len(user.totp_user) > 0` as "2FA enabled", and the old install carried an
**unconfigured** `totp_data` row (a TOTP secret the customer never set up) — so password-only login is
rejected. A **fresh 4.10.7 deploy has 0 TOTP rows and logs in fine** (verified). The demo (the only
existing install) was fresh-redeployed, so no live customer is affected; the catalog bump is safe for new
deploys.
## Observations (documented, NOT acted on)
1. **In-place upgrade remediation**: upgrading any pre-4.10 Crafty needs its unconfigured `totp_data`
(+`totp_recovery`) rows cleared, or the user logs in with a recovery code, else lockout. A safe
migration helper (clear TOTP rows that were never user-activated) would be a Crafty-side or
entrypoint concern — own task; currently moot (no other installs).
2. **Java 25 present** → no custom image needed to run latest MC; the earlier "may need a custom
temurin-25 image" worry is resolved by 4.10.7 itself.
3. **Dynamic connection panel**: render the live LAN IP + published range + per-server port on the app
page (vs static guidance) — a controller feature, own task.
4. **Bedrock (UDP 19132)** — out of scope; own task if Bedrock enters product scope.
5. **Internet exposure** (operator port-forward vs Felhom-operated relay vs Tailscale) — open design call.