docs: CHANGELOG + REPORT for crafty 4.10.7 bump, port range, guidance; flag in-place-upgrade TOTP lockout
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user