docs: REPORT for crafty seeded admin password (gokapi pattern); live-verified fresh install + API login
This commit is contained in:
@@ -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":"<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** |
|
||||
|
||||
## 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.
|
||||
|
||||
Reference in New Issue
Block a user