mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
bc7fff9dd7
Introduce an interactive credential recovery tool (scripts/recover-credentials.js) and accompanying documentation (documentation/admin-features/credential-recovery.md). Add npm script rmab:recover to package.json and wire the doc into TABLEOFCONTENTS.md. Improve docker/unified/app-start.sh to wait for local Redis to finish loading before initializing app services to avoid "LOADING" errors when queues start. The recovery script uses Prisma, runs entirely interactively via docker exec -it, performs DB changes in a single transaction, and persists a rotated CONFIG_ENCRYPTION_KEY to /app/config/.secrets and /etc/environment when needed.
3.7 KiB
3.7 KiB
Credential Recovery Script
Status: ✅ Implemented | Interactive recovery for lost CONFIG_ENCRYPTION_KEY or forgotten local admin password
Overview
Recovers from the "Invalid username or password" failure mode caused by a lost or rotated CONFIG_ENCRYPTION_KEY. Detects whether the key still works; either does a minimal password reset (preserves everything) or full recovery (rotates key + clears credentials that can no longer be decrypted).
When to Use
- Local admin gets "Invalid username or password" with credentials known to be correct
/app/config/.secretswas lost, truncated, or recreated- After an unintended
CONFIG_ENCRYPTION_KEYchange - See GitHub issue #200 for the symptom pattern
How to Run
docker exec -it <container-name> npm run rmab:recover
-itis required for the interactive prompts- Or directly:
docker exec -it <container-name> node /app/scripts/recover-credentials.js
What It Does
- Loads
DATABASE_URLandCONFIG_ENCRYPTION_KEYfrom env (falls back to/etc/environment) - Diagnoses key health by attempting to decrypt an existing encrypted Configuration row
- Lists local users (
authProvider='local', not soft-deleted); prompts for one - Prompts for new password twice (masked); validates length unless
ALLOW_WEAK_PASSWORD=true - Prints the exact plan (mode + what will be cleared); requires typing
confirmverbatim - Executes inside a single Prisma
$transaction - If key was rotated: writes new key to
/app/config/.secretsand/etc/environment
Two Modes (auto-detected)
Simple Password Reset (key works):
- Only updates the chosen user's
authToken(new bcrypt, re-encrypted) - No other data touched
- No container restart needed
Full Recovery (key broken):
- Generates new
CONFIG_ENCRYPTION_KEY(32 random bytes, base64) - For each
Configurationrow withencrypted=true: re-encrypts with new key if old decrypt succeeds, deletes the row if not - For
download_clientsJSON: re-encrypts each client password if possible, blanks it if not (URL/host/etc. preserved) - For all
User.authTokenvalues: re-encrypts if possible, clears if not (Plex/OIDC users re-OAuth on next login) - Overwrites target user's
authTokenwith fresh bcrypt encrypted with new key - Writes new key to
.secrets+/etc/environment - Container restart required after this mode
What Survives (Full Recovery Mode)
- All requests + request history
- Library mappings, organization templates, schedules, user accounts
- Non-encrypted Configuration rows (paths, log level, backend mode, etc.)
- Plex/OIDC users whose tokens decrypted successfully (no re-OAuth needed)
What User Re-enters After Full Recovery
- Plex auth token (or re-OAuth via login)
- Audiobookshelf API token (if used)
- OIDC client secret (if used)
- Prowlarr API key
- Download client passwords (per client)
- Any AI / Hardcover / Goodreads / notification provider secrets
Security
- CLI only — no HTTP endpoint, no auto-run, no rescue-mode env flag
- Requires
docker execaccess (= host root equivalent) - Refuses to accept any CLI arguments — all input via interactive prompts
- Does not echo or log password or key values
- Operation summary written to stdout; full audit info to app logger
- Idempotent within a single mode (re-runs are safe)
Failure Modes
- DB transaction fails → no changes committed, safe to re-run
- DB transaction commits but
.secrets//etc/environmentwrite fails → script prints the new key in plaintext with instructions for manual write (one-time exposure in operator's terminal)
Related
backend/services/auth.md— local auth flow + the decrypt-then-compare pathbackend/services/config.md— encryption format detailsdeployment/unified.md— entrypoint behavior and.secretspersistence