← back to Small Business Builder
scripts/deploy-kamatera.sh
86 lines
#!/usr/bin/env bash
# Deploy smb-builder to Kamatera at 45.61.58.125:9760 (IP:port, no public domain yet).
#
# REQUIRES EXPLICIT AUTH per Steve's standing rule for cncp-adjacent deploys.
# Run only after reading DEPLOY.md and confirming intent.
#
# Idempotent: re-running is safe — rsync syncs, psql migrations are guarded.
#
# Pre-reqs (set in this shell BEFORE running, do NOT inline as $VAR in bash):
# set -a; source /tmp/.smb_admin_token_<pid> ; set +a # exposes ADMIN_TOKEN
# (or just `export ADMIN_TOKEN="$(cat <secret-file>)"`)
#
# What this does:
# 1. rsync code → kamatera:/root/Projects/small-business-builder
# 2. createdb on Kamatera (skipped if exists)
# 3. run migrations
# 4. write .env with the ADMIN_TOKEN from this shell (no argv leak)
# 5. pm2 start + pm2 save
# 6. test http://45.61.58.125:9760/
set -euo pipefail
REMOTE="root@45.61.58.125"
REMOTE_DIR="/root/Projects/small-business-builder"
LOCAL_DIR="$HOME/Projects/small-business-builder"
if [ -z "${ADMIN_TOKEN:-}" ]; then
echo "FATAL: ADMIN_TOKEN env var not set in this shell." >&2
echo "Run: set -a; source /tmp/.smb_admin_token_<pid>; set +a then re-run this script." >&2
exit 1
fi
echo "[1/6] rsync code → $REMOTE:$REMOTE_DIR"
rsync -av --delete \
--exclude=node_modules --exclude=.git --exclude=logs --exclude='.env*' \
--exclude='_yolo_patches' --exclude='*.bak.*' \
"$LOCAL_DIR/" "$REMOTE:$REMOTE_DIR/"
echo "[2/6] ensure DB + role exist (sudo -u postgres for peer auth)"
# Pipe DB password via stdin so it never enters argv / ps / shell history.
DB_PW="${DB_PW:-$ADMIN_TOKEN}" # reuse admin token as DB pw if not set
ssh "$REMOTE" "sudo -u postgres psql" <<EOF
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='smb_builder') THEN
CREATE ROLE smb_builder WITH LOGIN PASSWORD '$DB_PW';
ELSE
ALTER ROLE smb_builder WITH PASSWORD '$DB_PW';
END IF;
END
\$\$;
SELECT 'CREATE DATABASE small_business_directory OWNER smb_builder'
WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname='small_business_directory')
\\gexec
GRANT ALL PRIVILEGES ON DATABASE small_business_directory TO smb_builder;
EOF
echo "[3/6] run migrations"
ssh "$REMOTE" "cd $REMOTE_DIR && for m in migrations/*.sql; do echo \"applying \$m\"; sudo -u postgres psql -d small_business_directory -f \"\$m\" || true; done"
echo "[4/6] write .env (token via stdin, never argv)"
# Pipe token via stdin so it never appears in argv / ps / shell history
ssh "$REMOTE" "cat > $REMOTE_DIR/.env" <<EOF
NODE_ENV=production
PORT=9760
DATABASE_URL=postgres://smb_builder:$DB_PW@localhost:5432/small_business_directory
ADMIN_TOKEN=$ADMIN_TOKEN
EOF
ssh "$REMOTE" "chmod 600 $REMOTE_DIR/.env"
echo "[5/6] npm install + pm2 start + save"
ssh "$REMOTE" "cd $REMOTE_DIR && npm install --omit=dev --no-audit --no-fund 2>&1 | tail -5"
ssh "$REMOTE" "cd $REMOTE_DIR && pm2 delete smb-builder 2>/dev/null; pm2 start ecosystem.config.cjs && pm2 save"
echo "[6/6] smoke test"
sleep 3
ssh "$REMOTE" "curl -s -o /dev/null -w 'http://localhost:9760/ → %{http_code}\n' --max-time 5 http://localhost:9760/"
echo ""
echo "From your laptop, with the same ADMIN_TOKEN value:"
echo " curl http://45.61.58.125:9760/healthz"
echo ""
echo "Done. Remember to:"
echo " • unset ADMIN_TOKEN in this shell"
echo " • rm /tmp/.smb_admin_token_*"
echo " • route the new token through ~/Projects/secrets-manager/cli.js add SMB_ADMIN_TOKEN"