Merge branch 'master' of https://code.bizgaze.com/Sravan/BizGaze_Remote
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
**/node_modules
|
||||
server/data.db
|
||||
server/data.db-wal
|
||||
server/data.db-shm
|
||||
**/*.log
|
||||
agent
|
||||
docs
|
||||
*.bat
|
||||
@@ -0,0 +1,19 @@
|
||||
# BizGaze Support — server secrets / config.
|
||||
# Copy this file to `.env` next to docker-compose.yml on the server and fill in
|
||||
# real values. The real `.env` is gitignored — NEVER commit credentials.
|
||||
# Compose injects these into the container via `env_file:`.
|
||||
|
||||
# Managed TURN relay (Metered) — makes WebRTC work on mobile/cellular & strict NATs.
|
||||
# Comma-separated URL list; username + credential from the Metered dashboard.
|
||||
TURN_URLS=turn:global.relay.metered.ca:80,turn:global.relay.metered.ca:80?transport=tcp,turn:global.relay.metered.ca:443,turns:global.relay.metered.ca:443?transport=tcp
|
||||
TURN_USERNAME=
|
||||
TURN_CREDENTIAL=
|
||||
|
||||
# Optional: open self-registration of the first/any team (1 to enable).
|
||||
# ALLOW_REGISTRATION=1
|
||||
|
||||
# Optional: shared secret for BizGaze SSO + signed webhook delivery.
|
||||
# SSO_SECRET=
|
||||
|
||||
# Optional: BizGaze webhook endpoint for session events.
|
||||
# BIZGAZE_WEBHOOK_URL=
|
||||
@@ -19,6 +19,10 @@ npm-debug.log*
|
||||
# Environment files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Local deploy trigger password (never commit)
|
||||
deploy.secret
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# 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)
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
# BizGaze Support — server image
|
||||
# Node 24 ships node:sqlite as a stable built-in (no flag), which db.js relies on.
|
||||
FROM node:24-alpine
|
||||
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /app/server
|
||||
|
||||
# Install deps first for layer caching (only `ws`, plus optional nodemailer)
|
||||
COPY server/package*.json ./
|
||||
RUN npm install --omit=dev --no-audit --no-fund
|
||||
|
||||
# App source
|
||||
COPY server/ ./
|
||||
|
||||
# Served HTTP port (NPM terminates TLS and proxies here). DB lives on a volume.
|
||||
ENV PORT=8090
|
||||
ENV DB_PATH=/data/data.db
|
||||
EXPOSE 8090
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# deploy.sh — run this ON THE SERVER, from inside the cloned repo
|
||||
# (the app lives at /opt/bizgaze-support).
|
||||
#
|
||||
# What it does:
|
||||
# 1. Snapshots the current working tree (code + .env + certs, excluding .git)
|
||||
# into a rotating backup, keeping the newest $KEEP_BACKUPS.
|
||||
# 2. Pulls the latest commit of $GIT_BRANCH (git reset --hard, so the box
|
||||
# always matches origin exactly).
|
||||
# 3. Rebuilds the image and recreates the container. The named data volume
|
||||
# (data.db) persists; the untracked .env / server/cert.pem / server/key.pem
|
||||
# are gitignored and therefore preserved across every pull.
|
||||
# 4. Verifies the app is serving.
|
||||
#
|
||||
# Usage (on the server):
|
||||
# cd /opt/bizgaze-support
|
||||
# ./deploy.sh # pull latest + rebuild
|
||||
# ./deploy.sh --no-pull # rebuild current checkout (no git pull)
|
||||
# ./deploy.sh --rollback # restore newest backup snapshot + rebuild
|
||||
#
|
||||
# Fire it from your laptop without logging in:
|
||||
# plink -ssh -P 61 -pw '<pw>' root@118.95.33.89 \
|
||||
# "cd /opt/bizgaze-support && ./deploy.sh"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GIT_BRANCH="${GIT_BRANCH:-master}"
|
||||
KEEP_BACKUPS="${KEEP_BACKUPS:-3}"
|
||||
CONTAINER="${CONTAINER:-bizgaze-support}"
|
||||
|
||||
cd "$(dirname "$(readlink -f "$0")")"
|
||||
APP_DIR="$(pwd)"
|
||||
BK_DIR="${APP_DIR}.backups"
|
||||
|
||||
log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
|
||||
ok() { printf '\033[1;32m ✓\033[0m %s\n' "$*"; }
|
||||
warn(){ printf '\033[1;33m ! %s\033[0m\n' "$*"; }
|
||||
die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ -d .git ] || die "Not a git checkout. Run the one-time bootstrap first (see DEPLOY.md)."
|
||||
command -v docker >/dev/null || die "docker not found on this host."
|
||||
|
||||
# --- args ---
|
||||
DO_PULL=1; ROLLBACK=0
|
||||
for a in "$@"; do case "$a" in
|
||||
--no-pull) DO_PULL=0 ;;
|
||||
--rollback) ROLLBACK=1 ;;
|
||||
-h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
*) die "Unknown argument: $a" ;;
|
||||
esac; done
|
||||
|
||||
snapshot() {
|
||||
mkdir -p "$BK_DIR"
|
||||
local ts rev
|
||||
ts="$(date +%Y%m%d-%H%M%S)"
|
||||
rev="$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
|
||||
log "Snapshot -> $BK_DIR/${ts}-${rev}.tgz"
|
||||
tar --exclude=./.git --exclude=./node_modules \
|
||||
--exclude=./server/node_modules -czf "$BK_DIR/${ts}-${rev}.tgz" -C "$APP_DIR" .
|
||||
# rotate: keep newest $KEEP_BACKUPS
|
||||
local old
|
||||
old="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) || true)"
|
||||
if [ -n "$old" ]; then
|
||||
echo "Pruning old backups:"; echo "$old" | sed 's/^/ rm /'
|
||||
echo "$old" | xargs -r rm -f
|
||||
fi
|
||||
}
|
||||
|
||||
rebuild() {
|
||||
[ -f .env ] || warn "No .env present — TURN/SSO secrets will be unset."
|
||||
log "Rebuilding and recreating the container …"
|
||||
docker compose config >/dev/null || die "docker-compose.yml is invalid."
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
}
|
||||
|
||||
verify() {
|
||||
log "Verifying /api/ice …"
|
||||
if docker exec "$CONTAINER" wget -qO- http://localhost:8090/api/ice 2>/dev/null | grep -q iceServers; then
|
||||
ok "App is serving."
|
||||
else
|
||||
warn "Could not confirm /api/ice — check: docker logs $CONTAINER"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- rollback mode ---
|
||||
if [ "$ROLLBACK" -eq 1 ]; then
|
||||
latest="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | head -n1 || true)"
|
||||
[ -n "$latest" ] || die "No backups found in $BK_DIR"
|
||||
log "Rolling back from: $latest"
|
||||
snapshot # snapshot the (broken) current state first
|
||||
tar -xzf "$latest" -C "$APP_DIR"
|
||||
rebuild; verify
|
||||
ok "Rolled back to $latest"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- normal deploy ---
|
||||
snapshot
|
||||
if [ "$DO_PULL" -eq 1 ]; then
|
||||
log "Fetching origin/$GIT_BRANCH …"
|
||||
git fetch origin "$GIT_BRANCH"
|
||||
git reset --hard "origin/$GIT_BRANCH" # untracked .env / *.pem are preserved
|
||||
ok "Now at $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)"
|
||||
fi
|
||||
rebuild
|
||||
verify
|
||||
ok "Deploy complete. Backups kept: $KEEP_BACKUPS (in $BK_DIR)."
|
||||
echo " Rollback with: ./deploy.sh --rollback"
|
||||
@@ -0,0 +1,31 @@
|
||||
# BizGaze Support — deployed behind the existing Nginx Proxy Manager.
|
||||
# No host ports are published: NPM reaches this container by name on the
|
||||
# shared `nginx_proxy_manager_default` network. TLS is terminated by NPM,
|
||||
# which proxies https://remote.bizgaze.com -> bizgaze-support:8090.
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
image: bizgaze-support:latest
|
||||
container_name: bizgaze-support
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PORT=8090
|
||||
- DB_PATH=/data/data.db
|
||||
# Secrets (TURN credentials, SSO_SECRET, BIZGAZE_WEBHOOK_URL, etc.) live in
|
||||
# a .env file next to this compose file. It is gitignored — never committed.
|
||||
# See .env.example for the expected keys.
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
volumes:
|
||||
- bizgaze_support_data:/data # persists data.db across rebuilds
|
||||
networks:
|
||||
- npm
|
||||
|
||||
networks:
|
||||
npm:
|
||||
external: true
|
||||
name: nginx_proxy_manager_default
|
||||
|
||||
volumes:
|
||||
bizgaze_support_data:
|
||||
@@ -0,0 +1,27 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
REM redeploy.bat - trigger a remote deploy FROM YOUR LAPTOP (Windows).
|
||||
REM Double-click, or run from a terminal. Pass deploy.sh flags through:
|
||||
REM redeploy.bat pull latest + rebuild
|
||||
REM redeploy.bat --no-pull rebuild current checkout
|
||||
REM redeploy.bat --rollback restore newest backup on the server
|
||||
REM
|
||||
REM Password order: %DEPLOY_PASS% -> deploy.secret file -> prompt.
|
||||
|
||||
set "HOST=118.95.33.89"
|
||||
set "PORT=61"
|
||||
set "USER=root"
|
||||
set "APPDIR=/opt/bizgaze-support"
|
||||
|
||||
REM Locate plink
|
||||
set "PLINK=plink"
|
||||
where plink >nul 2>nul || set "PLINK=C:\Program Files\PuTTY\plink.exe"
|
||||
|
||||
REM Resolve password
|
||||
set "PW=%DEPLOY_PASS%"
|
||||
if "!PW!"=="" if exist "%~dp0deploy.secret" set /p PW=<"%~dp0deploy.secret"
|
||||
if "!PW!"=="" set /p "PW=Server password for %USER%@%HOST%: "
|
||||
|
||||
echo ==^> Triggering deploy on %USER%@%HOST% (%APPDIR%) ...
|
||||
"%PLINK%" -ssh -batch -P %PORT% -pw "!PW!" %USER%@%HOST% "cd %APPDIR% && bash deploy.sh %*"
|
||||
endlocal
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# redeploy.sh — trigger a remote deploy FROM YOUR LAPTOP (Git Bash).
|
||||
# It SSHes into the server and runs the server-side ./deploy.sh.
|
||||
#
|
||||
# Usage:
|
||||
# ./redeploy.sh # pull latest + rebuild
|
||||
# ./redeploy.sh --no-pull # rebuild current checkout
|
||||
# ./redeploy.sh --rollback # restore newest backup on the server
|
||||
#
|
||||
# Password (in priority order):
|
||||
# 1. $DEPLOY_PASS environment variable
|
||||
# 2. a gitignored `deploy.secret` file next to this script (one line = the pw)
|
||||
# 3. hidden prompt
|
||||
set -euo pipefail
|
||||
|
||||
HOST=118.95.33.89
|
||||
PORT=61
|
||||
USER=root
|
||||
APPDIR=/opt/bizgaze-support
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Locate plink (PuTTY).
|
||||
PLINK="$(command -v plink 2>/dev/null || true)"
|
||||
[ -n "$PLINK" ] || PLINK="/c/Program Files/PuTTY/plink"
|
||||
[ -x "$PLINK" ] || { echo "ERROR: plink not found (install PuTTY or add to PATH)"; exit 1; }
|
||||
|
||||
# Resolve password.
|
||||
PW="${DEPLOY_PASS:-}"
|
||||
if [ -z "$PW" ] && [ -f "$DIR/deploy.secret" ]; then
|
||||
PW="$(tr -d '\r\n' < "$DIR/deploy.secret")"
|
||||
fi
|
||||
if [ -z "$PW" ]; then
|
||||
read -rsp "Server password for $USER@$HOST: " PW; echo
|
||||
fi
|
||||
|
||||
echo "==> Triggering deploy on $USER@$HOST ($APPDIR) …"
|
||||
exec "$PLINK" -ssh -batch -P "$PORT" -pw "$PW" "$USER@$HOST" "cd $APPDIR && bash deploy.sh $*"
|
||||
Reference in New Issue
Block a user