feat: welcome desk auth and operator password reset
First visit lands on /welcome instead of burying signup in Settings. Add a host CLI to reset passwords without a session, plus Settings change-password. Refresh as-built design docs and the Unraid operator guide.
This commit is contained in:
+89
-25
@@ -1,22 +1,49 @@
|
||||
# Deploy Investor Flow on Unraid
|
||||
|
||||
Two containers: **backend** (`:3001`, SQLite + queue) and **frontend** (`:3000`, Next.js, proxies `/api` to the backend). Git and Actions already live on this Unraid box at `http://unraid.local:3003/transnet/investor-flow`.
|
||||
Two containers: **backend** (`:3001`, SQLite + queue) and **frontend** (`:3000`, Next.js, proxies `/api` to the backend). Git, Actions, and the container registry live on this Unraid box at `http://unraid.local:3003/transnet/investor-flow` (HTTP registry also at `10.37.0.86:3003`).
|
||||
|
||||
The current Gitea repo has Actions enabled but **no runner registered**, so every CI run is cancelled. Follow "One-time: Gitea runner" below if you want push-to-main to test and publish images.
|
||||
This is the operator guide. As-built product/tech status lives in [`FUNCTIONAL_DESIGN.md`](./FUNCTIONAL_DESIGN.md) and [`TECH_DESIGN.md`](./TECH_DESIGN.md).
|
||||
|
||||
## What you get
|
||||
|
||||
| Path | Role |
|
||||
|---|---|
|
||||
| `docker-compose.yml` | Build-from-git stack (works on Unraid or a laptop) |
|
||||
| `docker-compose.yml` | Build-from-git stack (laptop or Unraid checkout) |
|
||||
| `deploy/unraid/compose.pull.yml` | Pull prebuilt images from the Gitea registry |
|
||||
| `deploy/unraid/.env.example` | Secrets + ports + data dir |
|
||||
| `deploy/unraid/act-runner-compose.yml` | Gitea act_runner so CI/CD actually runs |
|
||||
| `deploy/unraid/user-scripts/sync-and-up.sh` | Cron CD: `git pull` + `compose up --build` |
|
||||
| `.github/workflows/ci.yml` | Tests on every push / PR |
|
||||
| `.github/workflows/cd.yml` | Build + push images on `main` |
|
||||
| `deploy/unraid/.env.example` | Secrets + ports + data dir + image names |
|
||||
| `deploy/unraid/act-runner-compose.yml` | Gitea act_runner (label `ubuntu-latest`) |
|
||||
| `deploy/unraid/user-scripts/sync-and-up.sh` | Cron fallback: `git pull` + `compose up --build` |
|
||||
| `.github/workflows/ci.yml` | Tests on every push / PR; **build + push images on `main`** |
|
||||
| `.github/workflows/cd.yml` | Manual image rebuild (`workflow_dispatch`) without a new commit |
|
||||
|
||||
## Unraid layout (recommended)
|
||||
## The path a commit takes
|
||||
|
||||
```
|
||||
write code → git push origin main
|
||||
│
|
||||
▼
|
||||
Gitea Actions (act_runner)
|
||||
│
|
||||
┌──────────┴──────────┐
|
||||
▼ ▼
|
||||
Job: test Job: images
|
||||
frontend tests (only if test passed
|
||||
backend tests and the event is a
|
||||
backend typecheck push to main)
|
||||
│
|
||||
▼
|
||||
Gitea registry tags
|
||||
…-backend:{sha,latest}
|
||||
…-frontend:{sha,latest}
|
||||
│
|
||||
▼
|
||||
Unraid pulls (or rebuilds)
|
||||
and recreates the two containers
|
||||
```
|
||||
|
||||
Publishing images is **not** the same as rolling the running stack. After CI is green you still pull (mode A) or rebuild (mode B) on Unraid.
|
||||
|
||||
## Unraid layout (required)
|
||||
|
||||
Use a **cache (or single-disk) path** for SQLite. `/mnt/user/...` is FUSE and can corrupt WAL files.
|
||||
|
||||
@@ -43,9 +70,9 @@ nano /mnt/cache/appdata/investor-flow/.env
|
||||
|
||||
Required in `.env`:
|
||||
|
||||
- `IFLOW_SESSION_SECRET` — `openssl rand -hex 32`
|
||||
- `SEC_OPERATOR_EMAIL` — real address (SEC + Yahoo user-agent)
|
||||
- `LLM_PROVIDER_URL` — Ornith LAN URL, e.g. `http://10.37.0.165:30081/v1` (not `localhost`)
|
||||
- `IFLOW_SESSION_SECRET` - `openssl rand -hex 32`
|
||||
- `SEC_OPERATOR_EMAIL` - real address (SEC + Yahoo user-agent)
|
||||
- `LLM_PROVIDER_URL` - Ornith LAN URL, e.g. `http://10.37.0.165:30081/v1` (not `localhost`)
|
||||
- `IFLOW_DATA_DIR=/mnt/cache/appdata/investor-flow/data`
|
||||
|
||||
If you copy today's Mac DB into `data/`, also set `IFLOW_CRYPTO_KEY` to the same value the Mac used. If the Mac never set one, encrypted X/FRED rows used the built-in dev key; re-enter those keys in Admin after a fresh Unraid DB instead of guessing.
|
||||
@@ -58,7 +85,7 @@ scp app/server/data/investor-flow.db* \
|
||||
root@unraid.local:/mnt/cache/appdata/investor-flow/data/
|
||||
```
|
||||
|
||||
Build and start:
|
||||
### First start (build on Unraid)
|
||||
|
||||
```bash
|
||||
cd /mnt/cache/appdata/investor-flow/repo
|
||||
@@ -69,9 +96,11 @@ Open `http://unraid.local:3000`. Backend health: `http://unraid.local:3001/healt
|
||||
|
||||
Compose Manager plugin: create a stack whose project directory is the repo checkout and whose env file is `/mnt/cache/appdata/investor-flow/.env`.
|
||||
|
||||
Reverse proxy (SWAG / NPM): point the host at **frontend :3000 only**. The browser talks same-origin `/api`; the Next container reaches the backend on the compose network.
|
||||
Reverse proxy (SWAG / NPM): point the host at **frontend :3000 only**. The browser talks same-origin `/api`; the Next container reaches the backend on the compose network (`IFLOW_BACKEND_URL=http://backend:3001`).
|
||||
|
||||
## One-time: Gitea runner (unlocks CI + image CD)
|
||||
## Gitea runner (CI + image publish)
|
||||
|
||||
One-time. Without a runner labeled `ubuntu-latest`, Gitea marks every workflow **cancelled**.
|
||||
|
||||
1. Gitea → Site Administration → Actions → Runners → **Create new runner**. Copy the token.
|
||||
2. Unraid Docker: add insecure registry `10.37.0.86:3003` (Gitea HTTP) so pulls/pushes work. Restart Docker.
|
||||
@@ -86,18 +115,50 @@ docker compose -f deploy/unraid/act-runner-compose.yml up -d
|
||||
|
||||
4. Confirm the runner is **Idle** on the Gitea runners page.
|
||||
5. Repo → Settings → Actions → Secrets: `REGISTRY_TOKEN` = a Gitea token with `write:package` and `write:repository`.
|
||||
6. Push to `main`. CI should run tests; CD should push:
|
||||
6. Optional repo variable `REGISTRY` (default `10.37.0.86:3003`).
|
||||
7. Push to `main`. CI should run tests; on success it should push:
|
||||
|
||||
- `10.37.0.86:3003/transnet/investor-flow-backend:latest`
|
||||
- `10.37.0.86:3003/transnet/investor-flow-frontend:latest`
|
||||
- `10.37.0.86:3003/transnet/investor-flow-backend:latest` (and `:${sha}`)
|
||||
- `10.37.0.86:3003/transnet/investor-flow-frontend:latest` (and `:${sha}`)
|
||||
|
||||
Then switch `.env` image names to those registry tags and use `deploy/unraid/compose.pull.yml` so Unraid no longer builds on the array.
|
||||
Manual republish of the current `main` SHA (no new commit): Gitea → Actions → **CD** → Run workflow.
|
||||
|
||||
## CD that works before a runner exists
|
||||
## Two ways to run the stack after CI
|
||||
|
||||
Unraid → User Scripts → new script, paste `deploy/unraid/user-scripts/sync-and-up.sh`, schedule every 10 minutes (or after you push). It fast-forwards `main` and rebuilds only when HEAD moved.
|
||||
### A. Pull prebuilt images (preferred)
|
||||
|
||||
A push to Gitea is then: write code → `git push origin main` → cron on Unraid rebuilds containers.
|
||||
Point `.env` at the registry tags:
|
||||
|
||||
```
|
||||
IFLOW_IMAGE_BACKEND=10.37.0.86:3003/transnet/investor-flow-backend:latest
|
||||
IFLOW_IMAGE_FRONTEND=10.37.0.86:3003/transnet/investor-flow-frontend:latest
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
cd /mnt/cache/appdata/investor-flow/repo
|
||||
docker compose -f deploy/unraid/compose.pull.yml \
|
||||
--env-file /mnt/cache/appdata/investor-flow/.env pull
|
||||
docker compose -f deploy/unraid/compose.pull.yml \
|
||||
--env-file /mnt/cache/appdata/investor-flow/.env up -d
|
||||
```
|
||||
|
||||
`compose.pull.yml` reads `GITEA_REGISTRY` (default `unraid.local:3003`) and `IFLOW_TAG` (default `latest`). Keep those consistent with what CI pushed.
|
||||
|
||||
### B. Build from the git checkout
|
||||
|
||||
Leave image names as `investor-flow-backend:local` / `investor-flow-frontend:local` and:
|
||||
|
||||
```bash
|
||||
cd /mnt/cache/appdata/investor-flow/repo
|
||||
git fetch --prune origin main && git merge --ff-only origin/main
|
||||
docker compose --env-file /mnt/cache/appdata/investor-flow/.env up -d --build
|
||||
```
|
||||
|
||||
Or schedule `deploy/unraid/user-scripts/sync-and-up.sh` in Unraid User Scripts (every 10 minutes is enough). It fast-forwards `main` and rebuilds only when HEAD moved, then waits for both `/health` endpoints.
|
||||
|
||||
Do not mix A and B on the same compose project unless you know which tags `.env` pins. After you switch to A, Unraid no longer compiles Next/Node on the array.
|
||||
|
||||
## Day-2 operations
|
||||
|
||||
@@ -105,14 +166,17 @@ A push to Gitea is then: write code → `git push origin main` → cron on Unrai
|
||||
|---|---|
|
||||
| Logs | `docker compose logs -f --tail=200 backend frontend` |
|
||||
| Restart | `docker compose up -d` |
|
||||
| Update (pull mode) | `docker compose -f deploy/unraid/compose.pull.yml pull && docker compose -f deploy/unraid/compose.pull.yml up -d` |
|
||||
| Update (pull mode) | `compose.pull.yml pull` then `up -d` |
|
||||
| Update (build mode) | `git merge --ff-only origin/main` then `up -d --build` |
|
||||
| Backup DB | copy `/mnt/cache/appdata/investor-flow/data/investor-flow.db*` (stop backend first, or use SQLite backup) |
|
||||
| Reset a password | No email reset. On the host: `docker compose exec backend node --experimental-strip-types src/cli/reset-password.ts --list` then `--email you@x --password 'newpass'` (add `--clear-2fa` if TOTP blocks login). Locally: `cd app/server && npm run reset-password -- --email you@x --password 'newpass'`. Sign in, then change it in Settings. |
|
||||
| Ornith | keep `LLM_PROVIDER_URL` on the LAN IP; user LLM endpoint in Settings can stay `http://10.37.0.165:30081/v1` |
|
||||
| Queue / SMTP / X / FRED | Admin UI at `/admin/*` on the frontend |
|
||||
|
||||
The backend process must stay up for dealer-map snapshots and the queue. `restart: unless-stopped` plus Unraid array autostart covers that.
|
||||
The backend process must stay up for dealer-map snapshots, confluence evaluation, alert producers, and the adapter queue. `restart: unless-stopped` plus Unraid array autostart covers that.
|
||||
|
||||
## What this is not
|
||||
|
||||
- Not Vercel. Next standalone + the Node backend both run on Unraid.
|
||||
- `/reports` is still the thin HTML stub. A daily GEX briefing job is separate.
|
||||
- CI does not SSH into Unraid or call `docker compose` for you. It publishes images; you (or User Scripts / Compose Manager) roll them.
|
||||
- Do not publish `IFLOW_SESSION_SECRET`, `IFLOW_CRYPTO_KEY`, or Gitea tokens.
|
||||
|
||||
Reference in New Issue
Block a user