4c75db2029
- /api/v1/devices (register) + /api/v1/devices/remove — auth-required, validates platform (ios|android), upserts by token; e2e covers register/validation/auth/remove. - db device_tokens table + deviceTokens repo. - push.js: FCM HTTP v1 (Android) and APNs token-based over HTTP/2 (iOS) folded into the single push.sendToUser path alongside Web Push; each transport independently config-gated and a silent no-op without creds. Dead tokens pruned on 404/410. - docs: CLIENTS.md Phase B updated; DEPLOY.md env table adds FCM/APNs vars. e2e 117/117. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
156 lines
6.4 KiB
Markdown
156 lines
6.4 KiB
Markdown
# Deploying BizGaze Support
|
|
|
|
The app runs as a Docker container behind the existing **Nginx Proxy Manager**,
|
|
which terminates TLS and proxies `https://remote.bizgaze.com` → `bizgaze-support:8090`
|
|
on the shared `nginx_proxy_manager_default` network. No host ports are published.
|
|
|
|
Deployment model: **the server holds a git clone of this repo.** Each deploy is a
|
|
`git pull` + rebuild via [`deploy.sh`](deploy.sh). Two files are *not* in git and
|
|
live only on the server — they survive every pull:
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `.env` | Secrets — TURN credentials, optional `SSO_SECRET`, `BIZGAZE_WEBHOOK_URL`. See [.env.example](.env.example). |
|
|
| `server/cert.pem`, `server/key.pem` | Self-signed cert for the app's *optional* direct-HTTPS listener (8443). Not needed behind NPM, but harmless. |
|
|
|
|
Server facts:
|
|
- Host: `root@118.95.33.89` port `61`
|
|
- App path: `/opt/bizgaze-support`
|
|
- Data: Docker named volume `bizgaze_support_data` → `/data/data.db` (persists across rebuilds)
|
|
- Backups: `/opt/bizgaze-support.backups/` (newest 3 `.tgz` snapshots, auto-rotated)
|
|
|
|
---
|
|
|
|
## Operational guardrails (read before every deploy)
|
|
|
|
These are correctness/security invariants, not preferences. Breaking one degrades
|
|
or breaks the app even if the container starts fine.
|
|
|
|
- **Single instance only.** Chat, presence, and meeting (WebRTC) signaling use an
|
|
**in-process** registry. Do **not** scale to multiple replicas or place several
|
|
instances behind a round-robin load balancer — users on different processes
|
|
can't see each other's messages/calls. One container, one process.
|
|
- **`ALLOW_LOCAL_LOGIN` must NOT be set in production.** It's a dev-only escape
|
|
hatch that bypasses BizGaze SSO and the local-password lockout. Production logs
|
|
in via BizGaze only.
|
|
- **`BIZGAZE_DIRECTORY_TOKEN` is server-side only** — it's used by the server to
|
|
proxy directory lookups and must never be exposed to the browser/client.
|
|
- **HTML is served `Cache-Control: no-store` by design** so new builds land
|
|
immediately. Do not add an HTTP/CDN cache layer that caches `.html`. Static JS
|
|
(`icons.js`) is cache-busted with a `?v=` query, currently `?v=4`.
|
|
- **Node ≥ 22.5** (the image uses `node:24-alpine`) — required for the built-in
|
|
`node:sqlite` that `db.js` relies on. `deploy.sh` rebuilds the image, so
|
|
`npm install` (incl. `web-push`) happens automatically; no manual install.
|
|
- **No DB migration is required** for routine UI/chat releases. The `data.db`
|
|
volume persists across rebuilds; schema changes (when present) auto-apply on boot.
|
|
|
|
### Env vars to confirm in `.env`
|
|
`.env` lives only on the server (never in git) and must contain, beyond the TURN
|
|
secrets already documented:
|
|
|
|
| Group | Vars | Needed for |
|
|
|-------|------|-----------|
|
|
| Login / SSO | `BIZGAZE_LOGIN_URL`, `BIZGAZE_DIRECTORY_URL`, `BIZGAZE_DIRECTORY_TOKEN`, `SSO_SECRET` | BizGaze sign-in + directory search |
|
|
| Web Push | `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT` | Background push for browsers / installed PWA |
|
|
| Native push — Android | `FCM_SERVICE_ACCOUNT` (path to / inline Firebase service-account JSON) | FCM push to the Android app |
|
|
| Native push — iOS | `APNS_KEY` (path/inline `.p8`), `APNS_KEY_ID`, `APNS_TEAM_ID`, `APNS_BUNDLE_ID`, `APNS_PRODUCTION=1` | APNs push to the iOS app |
|
|
| Calls | `TURN_URLS` / `TURN_SECRET` (or `TURN_USERNAME`+`TURN_CREDENTIAL`) | Audio/video across NATs & mobile networks |
|
|
|
|
If the VAPID keys are missing, push silently no-ops (the app still runs). Push on
|
|
iOS additionally requires the user to **Add to Home Screen** (iOS 16.4+) — an
|
|
end-user step, not ops.
|
|
|
|
### Per-release verification
|
|
After deploy, open the app and check the browser console logs the expected build,
|
|
e.g. `Biz Connect build 2026-06-30-batch14`. That confirms the new HTML is being
|
|
served (not a stale cache).
|
|
|
|
---
|
|
|
|
## One-time bootstrap (server → git clone)
|
|
|
|
Run **once** to convert the existing folder into a git checkout without losing the
|
|
secrets. Prerequisite: the deployment files (Dockerfile, docker-compose.yml,
|
|
deploy.sh, etc.) are committed and pushed to `origin/master` first.
|
|
|
|
```bash
|
|
ssh -p 61 root@118.95.33.89 # or: plink -ssh -P 61 -pw '<pw>' root@118.95.33.89
|
|
|
|
# 1. Store git credentials so pulls are non-interactive (once per server).
|
|
git config --global credential.helper store
|
|
printf 'https://devops%%40bizgaze.com:Bizgaze%%40123@code.bizgaze.com\n' > ~/.git-credentials
|
|
chmod 600 ~/.git-credentials
|
|
|
|
# 2. Stash the live secrets.
|
|
cd /opt
|
|
cp -a bizgaze-support /opt/bizgaze-support.preclone.bak
|
|
mkdir -p /tmp/bzsecrets
|
|
cp bizgaze-support/.env /tmp/bzsecrets/ 2>/dev/null || true
|
|
cp bizgaze-support/server/cert.pem /tmp/bzsecrets/ 2>/dev/null || true
|
|
cp bizgaze-support/server/key.pem /tmp/bzsecrets/ 2>/dev/null || true
|
|
|
|
# 3. Replace the folder with a fresh clone.
|
|
rm -rf bizgaze-support
|
|
git clone https://code.bizgaze.com/Sravan/BizGaze_Remote.git bizgaze-support
|
|
cd bizgaze-support
|
|
|
|
# 4. Restore the secrets the clone doesn't carry.
|
|
cp /tmp/bzsecrets/.env ./.env
|
|
cp /tmp/bzsecrets/cert.pem ./server/cert.pem 2>/dev/null || true
|
|
cp /tmp/bzsecrets/key.pem ./server/key.pem 2>/dev/null || true
|
|
rm -rf /tmp/bzsecrets
|
|
|
|
# 5. Build & launch.
|
|
chmod +x deploy.sh
|
|
docker compose up -d --build
|
|
docker compose ps
|
|
```
|
|
|
|
If `.env` did not exist yet, create it from the template and fill in the TURN secret:
|
|
|
|
```bash
|
|
cp .env.example .env && nano .env
|
|
```
|
|
|
|
---
|
|
|
|
## Routine deploy
|
|
|
|
After pushing changes to `origin/master`:
|
|
|
|
```bash
|
|
ssh -p 61 root@118.95.33.89 'cd /opt/bizgaze-support && ./deploy.sh'
|
|
```
|
|
|
|
`deploy.sh` snapshots the current tree (keeping 3 backups), `git reset --hard`s to
|
|
`origin/master`, rebuilds, and verifies `/api/ice`. Flags:
|
|
|
|
- `./deploy.sh --no-pull` — rebuild the current checkout without pulling
|
|
- `./deploy.sh --rollback` — restore the newest backup snapshot and rebuild
|
|
|
|
---
|
|
|
|
## Verify
|
|
|
|
```bash
|
|
curl https://remote.bizgaze.com/api/ice
|
|
```
|
|
|
|
Response must list the public STUN entry **and** a TURN entry at
|
|
`global.relay.metered.ca`. If only STUN appears, `.env` isn't reaching the
|
|
container — check `docker exec bizgaze-support env | grep TURN`.
|
|
|
|
---
|
|
|
|
## Rollback
|
|
|
|
```bash
|
|
cd /opt/bizgaze-support && ./deploy.sh --rollback # newest snapshot
|
|
# or restore a specific snapshot:
|
|
ls -1t /opt/bizgaze-support.backups/*.tgz
|
|
tar -xzf /opt/bizgaze-support.backups/<stamp>.tgz -C /opt/bizgaze-support && docker compose up -d --build
|
|
```
|
|
|
|
The `data.db` volume is never overwritten by a rebuild, so data is retained
|
|
regardless of code version.
|