#!/usr/bin/env bash # Bring the whole platform up locally, from nothing, in one command. # # Everything runs on this machine and touches no production system: Postgres and # Mosquitto in containers, the server as a local binary with the web app built # into it. Re-running it is safe - it reuses the containers and the database. # # Ports are deliberately odd. Docker Desktop itself listens on 127.0.0.1:8080, # which is how an earlier run of this ended up talking to something that was not # the server at all. set -euo pipefail cd "$(dirname "$0")" PORT=${PORT:-8088} PG_PORT=${PG_PORT:-55432} MQTT_PORT=${MQTT_PORT:-51883} STATE=${STATE:-.local} export DATABASE_URL="postgres://postgres:test@127.0.0.1:${PG_PORT}/behavision" mkdir -p "$STATE/mosquitto" step() { printf '\n\033[1m%s\033[0m\n' "$*"; } step "1. Postgres (pgvector - migration 001 needs the extension)" docker inspect bv-pg >/dev/null 2>&1 || docker run -d --name bv-pg \ -p "${PG_PORT}:5432" -e POSTGRES_PASSWORD=test -e POSTGRES_DB=behavision \ pgvector/pgvector:pg16 >/dev/null docker start bv-pg >/dev/null 2>&1 || true until docker exec bv-pg pg_isready -U postgres >/dev/null 2>&1; do sleep 1; done for f in server/migrations/*.sql; do docker exec -i bv-pg psql -U postgres -d behavision -v ON_ERROR_STOP=1 -q < "$f" done echo " migrations applied" step "2. Build (the web app builds INTO the Go module, so it goes first)" (cd web && npm install --silent && npm run build >/dev/null) (cd server && go build -o "../$STATE/bv-server" ./cmd/behavision-server) echo " built $STATE/bv-server" step "3. Encryption key (camera and broker passwords are sealed with it)" if [ ! -f "$STATE/env.sh" ]; then KEY=$("./$STATE/bv-server" provision key -raw 2>/dev/null) cat > "$STATE/env.sh" < "$STATE/mosquitto/mosquitto.conf" < "$STATE/mosquitto/acl" : > "$STATE/mosquitto/passwd" fi docker inspect bv-mqtt >/dev/null 2>&1 || docker run -d --name bv-mqtt \ -p "${MQTT_PORT}:1883" -v "$PWD/$STATE/mosquitto:/mosquitto/config" \ eclipse-mosquitto:2 >/dev/null docker start bv-mqtt >/dev/null 2>&1 || true sleep 1 docker exec bv-mqtt mosquitto_passwd -b /mosquitto/config/passwd \ behavision-server "$MQTT_PASSWORD" >/dev/null 2>&1 || true docker restart bv-mqtt >/dev/null echo " broker on ${MQTT_PORT}" step "5. First accounts" # Idempotent throughout: every provision subcommand upserts, so re-running this # resets these passwords rather than failing. "./$STATE/bv-server" provision user -email admin@loyaly.ai -role admin \ -name "Loyaly Platform" -password 'loyaly-platform-2026' >/dev/null # A tenant to sign in as. In the real flow a platform admin creates this from # Companies -> New company; it is seeded here so a fresh database has a working # login without seven steps first. Creating another one through the UI still # exercises the real path. "./$STATE/bv-server" provision client -slug tenext-retail -name "TeNext Retail" >/dev/null "./$STATE/bv-server" provision user -client tenext-retail -email suriya@tenext.in \ -role owner -name "Suriya" -password 'tenext-2026' >/dev/null # The shop. Its broker password is re-rolled on every run - it is sealed and # never readable again - so it is pushed into Mosquitto here in the same breath. # A shop PC enrolled on an earlier run therefore has to be claimed again, which # is the right trade locally and is why this is not how production works. SITE_OUT=$("./$STATE/bv-server" provision site -client tenext-retail -slug chennai \ -name "TeNext Chennai" -tz Asia/Kolkata) BUSER=$(printf '%s' "$SITE_OUT" | sed -n "s/.*passwd \([^ ]*\) .*/\1/p") BPASS=$(printf '%s' "$SITE_OUT" | sed -n "s/.*passwd [^ ]* '\(.*\)'.*/\1/p") docker exec bv-mqtt mosquitto_passwd -b /mosquitto/config/passwd "$BUSER" "$BPASS" >/dev/null 2>&1 grep -q "^user $BUSER$" "$STATE/mosquitto/acl" || \ printf '\nuser %s\ntopic write bv/%s/#\n' "$BUSER" "$BUSER" >> "$STATE/mosquitto/acl" docker restart bv-mqtt >/dev/null printf ' platform admin admin@loyaly.ai / loyaly-platform-2026 (Companies only)\n' printf ' TeNext owner suriya@tenext.in / tenext-2026 (Shops, Live, Cameras, Customers, Reports)\n' step "6. Run" echo " http://127.0.0.1:${PORT}" exec "./$STATE/bv-server"