101 lines
5.9 KiB
Markdown
101 lines
5.9 KiB
Markdown
# Deploy — prod backend on the DO droplet (`lime` / lilith-store-backend)
|
|
|
|
Target (probed 2026-06-29): **`lime`** = lilith-store-backend, Ubuntu 24.04, public `209.38.51.98` · wg `10.9.0.5` · VPC `10.20.0.2`. Co-tenant: **mac-sync-server** (Bun). Postgres **16 + pgbouncer** (socket/pooler, not TCP). **Node 18** present — **NestJS 11 needs Node 20+** (the one box change). 74G free. SSH alias `lime` (root, `~/.ssh/id_ed25519_1984`).
|
|
|
|
Dev UI reaches prod over the **WG mesh** (`10.9.0.5:3210`) — no public TLS/DNS needed.
|
|
|
|
> ⚠️ These steps `sudo`-write a SHARED prod host. They were blocked under auto mode (correctly). Run them in a non-auto session, or grant a `Bash(ssh lime *)` permission rule, or run them yourself.
|
|
|
|
## 1. Node 20 on the droplet
|
|
```bash
|
|
ssh lime 'curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt-get install -y nodejs && node -v'
|
|
```
|
|
(mac-sync uses Bun, so a system Node bump is safe for it.)
|
|
|
|
## 2. Create the two DBs — on the DO **Managed** Postgres cluster
|
|
**There is no local Postgres.** The droplet's pgbouncer (`:6432`) fronts a **DO Managed Postgres cluster**: `private-lilith-store-pg-do-user-28217120-0.l.db.ondigitalocean.com:25060` (holds the live `quinn` DB). So `people` + `prospector` are **new databases on that managed cluster** (additive — does NOT touch `quinn`):
|
|
|
|
- **Via Terraform IaC** (the DO infra is Terraform-managed in `uvlava/terraform/do`). The DBs + dedicated users are already declared (`pg_databases` += people/prospector; `digitalocean_database_user.{people,prospector}`). Just apply:
|
|
```bash
|
|
cd ~/Code/@projects/uvlava/terraform/do
|
|
TF_VAR_do_token=<your DO token> terraform apply # additive: +2 dbs, +2 users, 0 destroy
|
|
terraform output -raw people_db_password
|
|
terraform output -raw prospector_db_password
|
|
terraform output -raw pg_host # private cluster host for the .env
|
|
```
|
|
- Services connect **directly to the managed endpoint** over SSL (skip the shared pgbouncer to avoid touching live pooling): `*_DB_HOST=private-lilith-store-pg-...`, `*_DB_PORT=25060`, `*_DB_SSL=true`. (Optionally add `[databases]` entries to `/etc/pgbouncer/pgbouncer.ini` + reload to pool them, but that touches shared infra.)
|
|
|
|
## 3. Apply migrations
|
|
```bash
|
|
# prospector
|
|
for f in 0001_prospector 0002_drafts 0003_corrections; do
|
|
ssh lime "sudo -u postgres psql -d prospector" < migrations/$f.sql ; done
|
|
# people (from the cocottetech repo)
|
|
ssh lime "sudo -u postgres psql -d people" < <people-service>/migrations/0001_people.sql
|
|
```
|
|
|
|
## 4. Ship the built code
|
|
Build locally, rsync dist + manifests, install prod deps on the droplet:
|
|
```bash
|
|
npm run build && npm run build -w @prospector/mcp-prospector
|
|
rsync -az --delete dist package.json package-lock.json migrations lime:/opt/prospector/
|
|
ssh lime 'cd /opt/prospector && npm ci --omit=dev'
|
|
# people-service likewise to /opt/people-service
|
|
```
|
|
|
|
## 5. Env on the droplet (`/opt/prospector/.env`)
|
|
```
|
|
NODE_ENV=production
|
|
PROSPECTOR_API_PORT=3210
|
|
PROSPECTOR_DB_HOST=private-lilith-store-pg-do-user-28217120-0.l.db.ondigitalocean.com
|
|
PROSPECTOR_DB_PORT=25060 # DO managed cluster (direct, SSL)
|
|
PROSPECTOR_DB_SSL=true
|
|
PROSPECTOR_DB_NAME=prospector
|
|
PROSPECTOR_DB_USER=prospector
|
|
PROSPECTOR_DB_PASSWORD=<from doctl databases user create>
|
|
PROSPECTOR_SERVICE_TOKEN=<strong-token>
|
|
PEOPLE_BASE_URL=http://127.0.0.1:3061
|
|
PEOPLE_SERVICE_TOKEN=<people-token>
|
|
MACSYNC_BASE_URL=http://127.0.0.1:3201 # mac-sync runs on this same droplet
|
|
MACSYNC_SERVICE_TOKEN=<macsync-token>
|
|
MACSYNC_DEVICE_ID=<device>
|
|
MRNUMBER_BASE_URL=https://my.transquinnftw.com
|
|
MRNUMBER_SERVICE_TOKEN=<mr-token>
|
|
```
|
|
(people-service gets its own `/opt/people-service/.env` with `PEOPLE_DB_*` + `PEOPLE_SERVICE_TOKEN`.)
|
|
|
|
## 6. systemd units (`/etc/systemd/system/{prospector,people-service}.service`)
|
|
```
|
|
[Service]
|
|
WorkingDirectory=/opt/prospector
|
|
EnvironmentFile=/opt/prospector/.env
|
|
ExecStart=/usr/bin/node dist/main.js
|
|
Restart=always
|
|
User=root
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
`sudo systemctl enable --now people-service prospector` → `curl localhost:3061/health`, `curl localhost:3210/health`.
|
|
|
|
## 7. Wire mac-sync → prospector webhook
|
|
In the @mac-sync server (same droplet): on a new inbound, fire-and-forget
|
|
`POST http://127.0.0.1:3210/internal/inbound` with `Authorization: Bearer $PROSPECTOR_SERVICE_TOKEN`, body `{handle, channel:'imessage', text, occurredAt, hasCallSignal?}`. Env-gated (`PROSPECTOR_WEBHOOK_URL`/token) so macsync runs standalone if unset. (Redo cleanly — the earlier agent left partial edits in @mac-sync.)
|
|
|
|
## 8. Point the dev UI at prod (over the mesh)
|
|
`web/.env.local`:
|
|
```
|
|
PROSPECTOR_API_URL=http://10.9.0.5:3210
|
|
PROSPECTOR_SERVICE_TOKEN=<the prod PROSPECTOR_SERVICE_TOKEN>
|
|
```
|
|
Restart `npm run dev -w @prospector/web`. The vite proxy injects the token; the panel now shows **real prod decisions**.
|
|
|
|
## Verify (go-live)
|
|
`/health` both services → real inbound (or `prospector_submit_inbound`) → appears in `prospector/activity` → kill-switch flip persists → dev UI shows it over the mesh.
|
|
|
|
## Post-migration notes (2026-06-29 unification)
|
|
- Run new migrations: for f in migrations/0006_bilingual.sql ; do ssh lime "sudo -u postgres psql -d prospector" < $f ; done
|
|
- Bilingual now in prospect_drafts (original/translated/detected_lang); Triage/Detail/Reports use dual when present (data from macsync inbound + future classifier trans).
|
|
- MCP (@packages/mcp-prospector) now exposes full tools (prospector_* + legacy mappings for cockpit parity): list, thread, draft, send, mr, pastebin, reports, markets, classify, submit, held, activity, etc. Use with PROSPECTOR_BASE_URL + TOKEN. Replaces LP mcp-prospector.
|
|
- UI fused: Triage = designs/main-view + inbox-ops + LP Stream; Reports = 4 reports + engine subs (Experiments/Patterns/Actions); Queue = queued-tasks + owed/backfill; etc. PWA install in Control.
|
|
- LP can now drop prospector (see MIGRATION-PLAN in session plan file for removal list + proxies during cutover).
|
|
- Rebuild/redeploy mcp + app after changes.
|