Appearance
Deploying the backend & agent
One script, run from your Mac: bz-backend/scripts/deploy.gcp.sh.
Commands
bash
cd bz-backend
./scripts/deploy.gcp.sh deploy bz-backend # sync + install + build + restart + health
./scripts/deploy.gcp.sh deploy bz-backend no-install # skip npm install (code-only change)
./scripts/deploy.gcp.sh push bz-agent # force rsync even if the VM dir is a repo
./scripts/deploy.gcp.sh pull bz-backend # git pull ON the VM (repo mode only)
./scripts/deploy.gcp.sh restart bz-tokens
./scripts/deploy.gcp.sh logs bz-backend 200
./scripts/deploy.gcp.sh status # pm2 table + all four ports
./scripts/deploy.gcp.sh sshApps: bz-backend · bz-agent · bz-tokens · qube-backend.
Deploy modes
deploy checks whether the VM's app directory is a git repo and picks a mode:
is_git_repo? → yes → git fetch + checkout + reset --hard origin/$BRANCH + clean -fd
→ no → rsync from your local checkoutAs of 2026-07, bz-backend on the VM is not a git repo, so it uses rsync.
What rsync copies
bash
rsync -az \
--exclude='.git/' --exclude='node_modules/' --exclude='.env' \
--exclude='dist/' --exclude='build/' --exclude='logs/' \
--exclude='.DS_Store' --exclude='*.log' \
"$LOCAL_DIR/" "$VM_USER@$VM_IP:$VM_DIR/"Three consequences of rsync mode
- Uncommitted local work goes to production. Your working tree is the deploy artefact.
- There is no
--delete. Files you removed locally persist on the VM. So does anything you copied there once and forgot. - Untracked scratch files ship too — debug scripts, notes, anything not matching an exclude.
archive/, new-backend/, microservices-backend/ and gateway/ all ship on every deploy. They are not mounted, but they are there.
The fix is one-off
Clone the repo on the VM with a PAT. deploy then auto-switches to git-pull mode for that app with no script edit — is_git_repo does the detection. That removes the whole class of problem.
Git-pull mode
bash
git merge --abort || true
git rebase --abort || true
git fetch origin $BRANCH
git checkout $BRANCH
git reset --hard origin/$BRANCH
git clean -fd -e .env -e node_modulesA hard reset. Anything edited directly on the VM is discarded — which is the point.
The install step
Unless you pass no-install:
bash
rm -rf node_modules/swap-sdk # so npm re-fetches the tagged version
npm install --no-audit --no-fund
node -p "require('./node_modules/swap-sdk/package.json').version" # printedrm -rf node_modules/swap-sdk is not sufficient on its own
package-lock.json pins swap-sdk by resolved commit. npm install obeys the lock and reinstalls the old commit even after the directory is deleted.
You must have already run, and committed:
bash
npm install github:blazpay/swap-sdk#vX.Y.Z --package-lock-onlyThis exact trap hit production on 2026-07-26: the deploy installed 1.9.1 despite a v1.12.0 pin. The script prints the installed version — read that line.
Build
| App | BUILD | What runs |
|---|---|---|
bz-backend | no | Nothing — it is plain Node ESM |
bz-agent | yes | npm run build (tsc → build/) |
bz-tokens | yes | npm run build |
qube-backend | no | — |
Restart
bash
pm2 restart '$PM2_NAME' --update-env
pm2 saveHard restart, never reload — and this is deliberate
swap-sdk is a git-tagged dependency. pm2 reload keeps the parent process and its require cache alive, so an upgraded SDK is silently ignored. pm2 restart recycles the process tree so new module code loads.
--update-env picks up .env changes without a separate step.
Health check
bash
sleep 6
ss -tlnp | grep ':$PORT ' # is it listening?
pm2 logs $PM2_NAME --lines 12 --nostreamExits non-zero if the port is not bound. Read the twelve log lines — a process that binds the port can still be throwing on every request.
Environment variables
.env is excluded from the rsync, deliberately
A new environment variable does not travel with the code. Add it on the VM manually:
bash
./scripts/deploy.gcp.sh ssh
nano ~/bz-backend/.env
pm2 restart bz-backend --update-env"The code deployed but the feature does not work" is almost always this. UNISWAP_API_KEY is the canonical case — the provider integration shipped and silently produced no routes.
Full list: environment variables.
Standard deploy
bash
# 1. commit on bishtNew
cd bz-backend
git add -A && git commit -m "…" && git push origin bishtNew
# 2. if swap-sdk changed, bump the pin AND the lock (see above)
# 3. add any new env vars on the VM FIRST
# 4. deploy
./scripts/deploy.gcp.sh deploy bz-backend
# 5. verify
./scripts/deploy.gcp.sh status
./scripts/deploy.gcp.sh logs bz-backend 100Step 3 before step 4
A restart with a missing variable means a broken feature until you notice and restart again.
Code-only change
bash
./scripts/deploy.gcp.sh deploy bz-backend no-installSkips npm install. Faster, and safe when package.json did not change.
Deploying the agent
bash
./scripts/deploy.gcp.sh deploy bz-agentCompiles on the VM (BUILD=yes). Verify types locally first:
bash
cd bz-agent && npm run check-typesbz-agent is the safest thing to deploy
It has no chain access, no keys that move funds, and nothing depends on it except the chat path. A bad agent deploy degrades classification; it cannot lose money.
defi-set/restart_agent.sh exists as a convenience wrapper.
After a deploy
□ ./scripts/deploy.gcp.sh status — all four ports bound
□ Installed swap-sdk version matches the pin (the script prints it)
□ logs show no repeated errors
□ A quote request returns routes
□ Crons ticking (grep the logs for cron activity)
□ Executor wallet has gas
□ If a contract was involved: fee accruing (/defi/fees/summary?force=1)Rollback
There is no automated rollback.
| Mode | Rollback |
|---|---|
| rsync | git checkout <previous> locally, deploy again |
| git-pull | BRANCH is hardcoded per app; reset the branch, or SSH and git reset --hard <sha> |
| Env var | Edit .env on the VM, pm2 restart --update-env |
| swap-sdk | Bump the pin and lock back, deploy |
Contract upgrades do not roll back this way
A UUPS upgrade is a chain transaction. Rolling back means deploying the previous implementation and upgrading to it — and the storage layout must still be compatible. See contracts & upgrades.
Logs
bash
./scripts/deploy.gcp.sh logs bz-backend 500On the VM: /home/bisht/.pm2/logs/bz-backend-{error,out}.log, merged, timestamped.
Every request logs [timestamp] METHOD url - IP: … - Origin: …. Useful greps:
| Grep | Finds |
|---|---|
/defi/quotes | Quote requests and per-aggregator failures |
Route via | Execution-engine route rejections |
Not swap calldata | Calldata-guard hits |
delivers no in-tx output | Probe rejections (solver providers) |
error creating record | DCA creation failures |
| A wallet address | That user's whole session |
Deprecated scripts
Still present. Do not run them.
| Script | Was |
|---|---|
scripts/deploy.sh | Azure 20.198.176.70 |
scripts/deploy.kamatera.sh | Kamatera 194.113.195.167 |