Master overview (PHASE4_PRODUCTION_INFRASTRUCTURE.md) plus five detail docs (PRODUCTION_DEPLOYMENT, PRODUCTION_NETWORK_SECURITY, BACKUP_DR, OBSERVABILITY, CAPACITY_PLANNING), a master PRODUCTION_VALIDATION_CHECKLIST, and 12 runbooks (first deployment, normal deploy, rollback, Postgres restore, VM rebuild for both hosts, Docker TLS rotation, TLS renewal, owner recovery, stuck Lab cleanup, failed migration, backup failure, disk failure, Lab Host resource pressure). PRODUCTION_NETWORK_SECURITY.md prominently documents the one genuine architectural gap this phase surfaced: the Gateway's existing env.internal_ip mechanism for reaching a Lab container assumes Gateway and Lab share a Docker daemon, which breaks once Labs run on a genuinely separate rn-lab-host-01 VM. The network-policy half is built (a firewall allowance for Gateway->Lab-Host on a published port range); the application half (Provisioner/Gateway address handling) is an explicit, reviewed, NOT-YET-BUILT follow-up flagged there rather than silently decided. Updated LAB_ARCHITECTURE.md, ENGINEERING_SOP.md, README.md, and platform/README.md with Phase 4 pointers, consistent with how every prior phase updated these. Status: PHASE 4 BUILD COMPLETE / PRODUCTION DEPLOYMENT PENDING HARDWARE.
28 lines
1.3 KiB
Markdown
28 lines
1.3 KiB
Markdown
# Runbook: Owner Account Recovery
|
|
|
|
**Locked out with zero working owner accounts** (all deactivated, forgot the only owner's
|
|
password, etc.):
|
|
|
|
```bash
|
|
ssh rootnode-deploy@rn-platform-01
|
|
docker exec -it rootnode-platform-api-1 sh
|
|
node bootstrap-owner.js [email protected] "Your Name"
|
|
# bootstrap-owner.js refuses to run if an active owner already exists UNLESS the target email
|
|
# belongs to an EXISTING instructor row — in that case it promotes them to owner. Point it at
|
|
# any known instructor email to recover through them, or a brand-new email to create a fresh
|
|
# owner outright if the instructors table itself is in an unknown state.
|
|
```
|
|
|
|
**Forgot password, account still active and you have SSH access:**
|
|
|
|
```bash
|
|
docker exec -it rootnode-platform-postgres-1 psql -U rootnode_platform -c \
|
|
"SELECT instructor_id, email, role, status FROM instructors WHERE role='owner';"
|
|
# Then use another owner's account to reset via /admin -> Instructors -> [account] -> Reset
|
|
# Password, OR re-run bootstrap-owner.js targeting that email (also resets the password).
|
|
```
|
|
|
|
**Never** hand-edit `password_hash` in the database — it's `scrypt(salt):hash` in a specific
|
|
format (`platform/api/src/auth/password.js`); a malformed value just breaks login rather than
|
|
setting a usable password. Always go through `bootstrap-owner.js` or the admin UI's reset flow.
|