Sravan 1 tydzień temu
rodzic
commit
f6ebaa7bfb
9 zmienionych plików z 367 dodań i 0 usunięć
  1. 8
    0
      .dockerignore
  2. 19
    0
      .env.example
  3. 4
    0
      .gitignore
  4. 109
    0
      DEPLOY.md
  5. 20
    0
      Dockerfile
  6. 110
    0
      deploy.sh
  7. 31
    0
      docker-compose.yml
  8. 27
    0
      redeploy.bat
  9. 39
    0
      redeploy.sh

+ 8
- 0
.dockerignore Wyświetl plik

@@ -0,0 +1,8 @@
1
+**/node_modules
2
+server/data.db
3
+server/data.db-wal
4
+server/data.db-shm
5
+**/*.log
6
+agent
7
+docs
8
+*.bat

+ 19
- 0
.env.example Wyświetl plik

@@ -0,0 +1,19 @@
1
+# BizGaze Support — server secrets / config.
2
+# Copy this file to `.env` next to docker-compose.yml on the server and fill in
3
+# real values. The real `.env` is gitignored — NEVER commit credentials.
4
+# Compose injects these into the container via `env_file:`.
5
+
6
+# Managed TURN relay (Metered) — makes WebRTC work on mobile/cellular & strict NATs.
7
+# Comma-separated URL list; username + credential from the Metered dashboard.
8
+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
9
+TURN_USERNAME=
10
+TURN_CREDENTIAL=
11
+
12
+# Optional: open self-registration of the first/any team (1 to enable).
13
+# ALLOW_REGISTRATION=1
14
+
15
+# Optional: shared secret for BizGaze SSO + signed webhook delivery.
16
+# SSO_SECRET=
17
+
18
+# Optional: BizGaze webhook endpoint for session events.
19
+# BIZGAZE_WEBHOOK_URL=

+ 4
- 0
.gitignore Wyświetl plik

@@ -19,6 +19,10 @@ npm-debug.log*
19 19
 # Environment files
20 20
 .env
21 21
 .env.*
22
+!.env.example
23
+
24
+# Local deploy trigger password (never commit)
25
+deploy.secret
22 26
 
23 27
 # Build output
24 28
 dist/

+ 109
- 0
DEPLOY.md Wyświetl plik

@@ -0,0 +1,109 @@
1
+# Deploying BizGaze Support
2
+
3
+The app runs as a Docker container behind the existing **Nginx Proxy Manager**,
4
+which terminates TLS and proxies `https://remote.bizgaze.com` → `bizgaze-support:8090`
5
+on the shared `nginx_proxy_manager_default` network. No host ports are published.
6
+
7
+Deployment model: **the server holds a git clone of this repo.** Each deploy is a
8
+`git pull` + rebuild via [`deploy.sh`](deploy.sh). Two files are *not* in git and
9
+live only on the server — they survive every pull:
10
+
11
+| File | Purpose |
12
+|------|---------|
13
+| `.env` | Secrets — TURN credentials, optional `SSO_SECRET`, `BIZGAZE_WEBHOOK_URL`. See [.env.example](.env.example). |
14
+| `server/cert.pem`, `server/key.pem` | Self-signed cert for the app's *optional* direct-HTTPS listener (8443). Not needed behind NPM, but harmless. |
15
+
16
+Server facts:
17
+- Host: `root@118.95.33.89` port `61`
18
+- App path: `/opt/bizgaze-support`
19
+- Data: Docker named volume `bizgaze_support_data` → `/data/data.db` (persists across rebuilds)
20
+- Backups: `/opt/bizgaze-support.backups/` (newest 3 `.tgz` snapshots, auto-rotated)
21
+
22
+---
23
+
24
+## One-time bootstrap (server → git clone)
25
+
26
+Run **once** to convert the existing folder into a git checkout without losing the
27
+secrets. Prerequisite: the deployment files (Dockerfile, docker-compose.yml,
28
+deploy.sh, etc.) are committed and pushed to `origin/master` first.
29
+
30
+```bash
31
+ssh -p 61 root@118.95.33.89          # or: plink -ssh -P 61 -pw '<pw>' root@118.95.33.89
32
+
33
+# 1. Store git credentials so pulls are non-interactive (once per server).
34
+git config --global credential.helper store
35
+printf 'https://devops%%40bizgaze.com:Bizgaze%%40123@code.bizgaze.com\n' > ~/.git-credentials
36
+chmod 600 ~/.git-credentials
37
+
38
+# 2. Stash the live secrets.
39
+cd /opt
40
+cp -a bizgaze-support /opt/bizgaze-support.preclone.bak
41
+mkdir -p /tmp/bzsecrets
42
+cp bizgaze-support/.env                /tmp/bzsecrets/ 2>/dev/null || true
43
+cp bizgaze-support/server/cert.pem     /tmp/bzsecrets/ 2>/dev/null || true
44
+cp bizgaze-support/server/key.pem      /tmp/bzsecrets/ 2>/dev/null || true
45
+
46
+# 3. Replace the folder with a fresh clone.
47
+rm -rf bizgaze-support
48
+git clone https://code.bizgaze.com/Sravan/BizGaze_Remote.git bizgaze-support
49
+cd bizgaze-support
50
+
51
+# 4. Restore the secrets the clone doesn't carry.
52
+cp /tmp/bzsecrets/.env       ./.env
53
+cp /tmp/bzsecrets/cert.pem   ./server/cert.pem 2>/dev/null || true
54
+cp /tmp/bzsecrets/key.pem    ./server/key.pem  2>/dev/null || true
55
+rm -rf /tmp/bzsecrets
56
+
57
+# 5. Build & launch.
58
+chmod +x deploy.sh
59
+docker compose up -d --build
60
+docker compose ps
61
+```
62
+
63
+If `.env` did not exist yet, create it from the template and fill in the TURN secret:
64
+
65
+```bash
66
+cp .env.example .env && nano .env
67
+```
68
+
69
+---
70
+
71
+## Routine deploy
72
+
73
+After pushing changes to `origin/master`:
74
+
75
+```bash
76
+ssh -p 61 root@118.95.33.89 'cd /opt/bizgaze-support && ./deploy.sh'
77
+```
78
+
79
+`deploy.sh` snapshots the current tree (keeping 3 backups), `git reset --hard`s to
80
+`origin/master`, rebuilds, and verifies `/api/ice`. Flags:
81
+
82
+- `./deploy.sh --no-pull` — rebuild the current checkout without pulling
83
+- `./deploy.sh --rollback` — restore the newest backup snapshot and rebuild
84
+
85
+---
86
+
87
+## Verify
88
+
89
+```bash
90
+curl https://remote.bizgaze.com/api/ice
91
+```
92
+
93
+Response must list the public STUN entry **and** a TURN entry at
94
+`global.relay.metered.ca`. If only STUN appears, `.env` isn't reaching the
95
+container — check `docker exec bizgaze-support env | grep TURN`.
96
+
97
+---
98
+
99
+## Rollback
100
+
101
+```bash
102
+cd /opt/bizgaze-support && ./deploy.sh --rollback   # newest snapshot
103
+# or restore a specific snapshot:
104
+ls -1t /opt/bizgaze-support.backups/*.tgz
105
+tar -xzf /opt/bizgaze-support.backups/<stamp>.tgz -C /opt/bizgaze-support && docker compose up -d --build
106
+```
107
+
108
+The `data.db` volume is never overwritten by a rebuild, so data is retained
109
+regardless of code version.

+ 20
- 0
Dockerfile Wyświetl plik

@@ -0,0 +1,20 @@
1
+# BizGaze Support — server image
2
+# Node 24 ships node:sqlite as a stable built-in (no flag), which db.js relies on.
3
+FROM node:24-alpine
4
+
5
+ENV NODE_ENV=production
6
+WORKDIR /app/server
7
+
8
+# Install deps first for layer caching (only `ws`, plus optional nodemailer)
9
+COPY server/package*.json ./
10
+RUN npm install --omit=dev --no-audit --no-fund
11
+
12
+# App source
13
+COPY server/ ./
14
+
15
+# Served HTTP port (NPM terminates TLS and proxies here). DB lives on a volume.
16
+ENV PORT=8090
17
+ENV DB_PATH=/data/data.db
18
+EXPOSE 8090
19
+
20
+CMD ["node", "server.js"]

+ 110
- 0
deploy.sh Wyświetl plik

@@ -0,0 +1,110 @@
1
+#!/usr/bin/env bash
2
+#
3
+# deploy.sh — run this ON THE SERVER, from inside the cloned repo
4
+#             (the app lives at /opt/bizgaze-support).
5
+#
6
+# What it does:
7
+#   1. Snapshots the current working tree (code + .env + certs, excluding .git)
8
+#      into a rotating backup, keeping the newest $KEEP_BACKUPS.
9
+#   2. Pulls the latest commit of $GIT_BRANCH (git reset --hard, so the box
10
+#      always matches origin exactly).
11
+#   3. Rebuilds the image and recreates the container. The named data volume
12
+#      (data.db) persists; the untracked .env / server/cert.pem / server/key.pem
13
+#      are gitignored and therefore preserved across every pull.
14
+#   4. Verifies the app is serving.
15
+#
16
+# Usage (on the server):
17
+#   cd /opt/bizgaze-support
18
+#   ./deploy.sh                # pull latest + rebuild
19
+#   ./deploy.sh --no-pull      # rebuild current checkout (no git pull)
20
+#   ./deploy.sh --rollback     # restore newest backup snapshot + rebuild
21
+#
22
+# Fire it from your laptop without logging in:
23
+#   plink -ssh -P 61 -pw '<pw>' root@118.95.33.89 \
24
+#     "cd /opt/bizgaze-support && ./deploy.sh"
25
+
26
+set -euo pipefail
27
+
28
+GIT_BRANCH="${GIT_BRANCH:-master}"
29
+KEEP_BACKUPS="${KEEP_BACKUPS:-3}"
30
+CONTAINER="${CONTAINER:-bizgaze-support}"
31
+
32
+cd "$(dirname "$(readlink -f "$0")")"
33
+APP_DIR="$(pwd)"
34
+BK_DIR="${APP_DIR}.backups"
35
+
36
+log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
37
+ok()  { printf '\033[1;32m  ✓\033[0m %s\n' "$*"; }
38
+warn(){ printf '\033[1;33m  ! %s\033[0m\n' "$*"; }
39
+die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
40
+
41
+[ -d .git ] || die "Not a git checkout. Run the one-time bootstrap first (see DEPLOY.md)."
42
+command -v docker >/dev/null || die "docker not found on this host."
43
+
44
+# --- args ---
45
+DO_PULL=1; ROLLBACK=0
46
+for a in "$@"; do case "$a" in
47
+  --no-pull) DO_PULL=0 ;;
48
+  --rollback) ROLLBACK=1 ;;
49
+  -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
50
+  *) die "Unknown argument: $a" ;;
51
+esac; done
52
+
53
+snapshot() {
54
+  mkdir -p "$BK_DIR"
55
+  local ts rev
56
+  ts="$(date +%Y%m%d-%H%M%S)"
57
+  rev="$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
58
+  log "Snapshot -> $BK_DIR/${ts}-${rev}.tgz"
59
+  tar --exclude=./.git --exclude=./node_modules \
60
+      --exclude=./server/node_modules -czf "$BK_DIR/${ts}-${rev}.tgz" -C "$APP_DIR" .
61
+  # rotate: keep newest $KEEP_BACKUPS
62
+  local old
63
+  old="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) || true)"
64
+  if [ -n "$old" ]; then
65
+    echo "Pruning old backups:"; echo "$old" | sed 's/^/  rm /'
66
+    echo "$old" | xargs -r rm -f
67
+  fi
68
+}
69
+
70
+rebuild() {
71
+  [ -f .env ] || warn "No .env present — TURN/SSO secrets will be unset."
72
+  log "Rebuilding and recreating the container …"
73
+  docker compose config >/dev/null || die "docker-compose.yml is invalid."
74
+  docker compose up -d --build
75
+  docker compose ps
76
+}
77
+
78
+verify() {
79
+  log "Verifying /api/ice …"
80
+  if docker exec "$CONTAINER" wget -qO- http://localhost:8090/api/ice 2>/dev/null | grep -q iceServers; then
81
+    ok "App is serving."
82
+  else
83
+    warn "Could not confirm /api/ice — check: docker logs $CONTAINER"
84
+  fi
85
+}
86
+
87
+# --- rollback mode ---
88
+if [ "$ROLLBACK" -eq 1 ]; then
89
+  latest="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | head -n1 || true)"
90
+  [ -n "$latest" ] || die "No backups found in $BK_DIR"
91
+  log "Rolling back from: $latest"
92
+  snapshot                                   # snapshot the (broken) current state first
93
+  tar -xzf "$latest" -C "$APP_DIR"
94
+  rebuild; verify
95
+  ok "Rolled back to $latest"
96
+  exit 0
97
+fi
98
+
99
+# --- normal deploy ---
100
+snapshot
101
+if [ "$DO_PULL" -eq 1 ]; then
102
+  log "Fetching origin/$GIT_BRANCH …"
103
+  git fetch origin "$GIT_BRANCH"
104
+  git reset --hard "origin/$GIT_BRANCH"      # untracked .env / *.pem are preserved
105
+  ok "Now at $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)"
106
+fi
107
+rebuild
108
+verify
109
+ok "Deploy complete. Backups kept: $KEEP_BACKUPS (in $BK_DIR)."
110
+echo "   Rollback with:  ./deploy.sh --rollback"

+ 31
- 0
docker-compose.yml Wyświetl plik

@@ -0,0 +1,31 @@
1
+# BizGaze Support — deployed behind the existing Nginx Proxy Manager.
2
+# No host ports are published: NPM reaches this container by name on the
3
+# shared `nginx_proxy_manager_default` network. TLS is terminated by NPM,
4
+# which proxies https://remote.bizgaze.com -> bizgaze-support:8090.
5
+services:
6
+  app:
7
+    build: .
8
+    image: bizgaze-support:latest
9
+    container_name: bizgaze-support
10
+    restart: unless-stopped
11
+    environment:
12
+      - PORT=8090
13
+      - DB_PATH=/data/data.db
14
+    # Secrets (TURN credentials, SSO_SECRET, BIZGAZE_WEBHOOK_URL, etc.) live in
15
+    # a .env file next to this compose file. It is gitignored — never committed.
16
+    # See .env.example for the expected keys.
17
+    env_file:
18
+      - path: .env
19
+        required: false
20
+    volumes:
21
+      - bizgaze_support_data:/data   # persists data.db across rebuilds
22
+    networks:
23
+      - npm
24
+
25
+networks:
26
+  npm:
27
+    external: true
28
+    name: nginx_proxy_manager_default
29
+
30
+volumes:
31
+  bizgaze_support_data:

+ 27
- 0
redeploy.bat Wyświetl plik

@@ -0,0 +1,27 @@
1
+@echo off
2
+setlocal enabledelayedexpansion
3
+REM redeploy.bat - trigger a remote deploy FROM YOUR LAPTOP (Windows).
4
+REM Double-click, or run from a terminal. Pass deploy.sh flags through:
5
+REM   redeploy.bat               pull latest + rebuild
6
+REM   redeploy.bat --no-pull     rebuild current checkout
7
+REM   redeploy.bat --rollback    restore newest backup on the server
8
+REM
9
+REM Password order: %DEPLOY_PASS%  ->  deploy.secret file  ->  prompt.
10
+
11
+set "HOST=118.95.33.89"
12
+set "PORT=61"
13
+set "USER=root"
14
+set "APPDIR=/opt/bizgaze-support"
15
+
16
+REM Locate plink
17
+set "PLINK=plink"
18
+where plink >nul 2>nul || set "PLINK=C:\Program Files\PuTTY\plink.exe"
19
+
20
+REM Resolve password
21
+set "PW=%DEPLOY_PASS%"
22
+if "!PW!"=="" if exist "%~dp0deploy.secret" set /p PW=<"%~dp0deploy.secret"
23
+if "!PW!"=="" set /p "PW=Server password for %USER%@%HOST%: "
24
+
25
+echo ==^> Triggering deploy on %USER%@%HOST% (%APPDIR%) ...
26
+"%PLINK%" -ssh -batch -P %PORT% -pw "!PW!" %USER%@%HOST% "cd %APPDIR% && bash deploy.sh %*"
27
+endlocal

+ 39
- 0
redeploy.sh Wyświetl plik

@@ -0,0 +1,39 @@
1
+#!/usr/bin/env bash
2
+#
3
+# redeploy.sh — trigger a remote deploy FROM YOUR LAPTOP (Git Bash).
4
+# It SSHes into the server and runs the server-side ./deploy.sh.
5
+#
6
+# Usage:
7
+#   ./redeploy.sh              # pull latest + rebuild
8
+#   ./redeploy.sh --no-pull    # rebuild current checkout
9
+#   ./redeploy.sh --rollback   # restore newest backup on the server
10
+#
11
+# Password (in priority order):
12
+#   1. $DEPLOY_PASS environment variable
13
+#   2. a gitignored `deploy.secret` file next to this script (one line = the pw)
14
+#   3. hidden prompt
15
+set -euo pipefail
16
+
17
+HOST=118.95.33.89
18
+PORT=61
19
+USER=root
20
+APPDIR=/opt/bizgaze-support
21
+
22
+DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+
24
+# Locate plink (PuTTY).
25
+PLINK="$(command -v plink 2>/dev/null || true)"
26
+[ -n "$PLINK" ] || PLINK="/c/Program Files/PuTTY/plink"
27
+[ -x "$PLINK" ] || { echo "ERROR: plink not found (install PuTTY or add to PATH)"; exit 1; }
28
+
29
+# Resolve password.
30
+PW="${DEPLOY_PASS:-}"
31
+if [ -z "$PW" ] && [ -f "$DIR/deploy.secret" ]; then
32
+  PW="$(tr -d '\r\n' < "$DIR/deploy.secret")"
33
+fi
34
+if [ -z "$PW" ]; then
35
+  read -rsp "Server password for $USER@$HOST: " PW; echo
36
+fi
37
+
38
+echo "==> Triggering deploy on $USER@$HOST ($APPDIR) …"
39
+exec "$PLINK" -ssh -batch -P "$PORT" -pw "$PW" "$USER@$HOST" "cd $APPDIR && bash deploy.sh $*"

Ładowanie…
Anuluj
Zapisz