#!/usr/bin/env bash set -euo pipefail APP_PUBLIC_PORT="${APP_PUBLIC_PORT:-8080}" APP_FRONTEND_PORT="${APP_FRONTEND_PORT:-3000}" APP_BACKEND_PORT="${APP_BACKEND_PORT:-18080}" NANOBOT_HOME="${NANOBOT_HOME:-/root/.nanobot}" NANOBOT_AUTH_FILE="${NANOBOT_AUTH_FILE:-$NANOBOT_HOME/web_auth_users.json}" NANOBOT_RUNTIME_ENV_FILE="${NANOBOT_RUNTIME_ENV_FILE:-$NANOBOT_HOME/runtime.env}" log() { printf '[app-instance] %s\n' "$*" } require_file() { local path="$1" local message="$2" if [[ ! -f "$path" ]]; then printf '[app-instance] %s: %s\n' "$message" "$path" >&2 exit 1 fi } render_swarms_env_file() { local config_path="$1" local target_path="$2" CONFIG_PATH="$config_path" TARGET_PATH="$target_path" python3 - <<'PY' import json import os from pathlib import Path config_path = Path(os.environ["CONFIG_PATH"]) target_path = Path(os.environ["TARGET_PATH"]) data = json.loads(config_path.read_text(encoding="utf-8")) model = str(data.get("agents", {}).get("defaults", {}).get("model") or "").strip() if model and "/" not in model: model = f"openai/{model}" provider_cfg = data.get("providers", {}).get("openai", {}) or {} api_key = str(provider_cfg.get("apiKey") or "").strip() api_base = str(provider_cfg.get("apiBase") or "").strip() lines = [ '# Generated from /root/.nanobot/config.json for vendored swarms runtime.', 'WORKSPACE_DIR="/root/.nanobot/workspace"', 'SWARMS_VERBOSE_GLOBAL="False"', 'SWARMS_TELEMETRY_ON="false"', f'SWARMS_DEFAULT_MODEL="{model}"', f'OPENAI_API_KEY="{api_key}"', f'OPENAI_API_BASE="{api_base}"', f'OPENAI_BASE_URL="{api_base}"', ] target_path.write_text("\n".join(lines) + "\n", encoding="utf-8") PY } cleanup() { local status=$? if [[ -n "${NGINX_PID:-}" ]]; then kill "${NGINX_PID}" 2>/dev/null || true fi if [[ -n "${FRONTEND_PID:-}" ]]; then kill "${FRONTEND_PID}" 2>/dev/null || true fi if [[ -n "${BACKEND_PID:-}" ]]; then kill "${BACKEND_PID}" 2>/dev/null || true fi wait 2>/dev/null || true exit "$status" } trap cleanup EXIT INT TERM mkdir -p "$NANOBOT_HOME" "$NANOBOT_HOME/workspace" if [[ -f "$NANOBOT_RUNTIME_ENV_FILE" ]]; then set -a . "$NANOBOT_RUNTIME_ENV_FILE" set +a fi require_file "$NANOBOT_HOME/config.json" "Missing Boardware Genius config" require_file "$NANOBOT_AUTH_FILE" "Missing web auth users file" SWARMS_ENV_FILE="/opt/app/backend/third_party/swarms/.env" render_swarms_env_file "$NANOBOT_HOME/config.json" "$SWARMS_ENV_FILE" if [[ -f "$SWARMS_ENV_FILE" ]]; then set -a . "$SWARMS_ENV_FILE" set +a fi export NANOBOT_AUTH_FILE export NANOBOT_RUNTIME_ENV_FILE export PORT="$APP_FRONTEND_PORT" export HOSTNAME="127.0.0.1" log "starting backend on 127.0.0.1:${APP_BACKEND_PORT}" nanobot web --host 127.0.0.1 --port "$APP_BACKEND_PORT" & BACKEND_PID=$! log "starting frontend on 127.0.0.1:${APP_FRONTEND_PORT}" ( cd /opt/app/frontend node server.js ) & FRONTEND_PID=$! log "starting nginx on 0.0.0.0:${APP_PUBLIC_PORT}" nginx -c /opt/app/nginx.conf -g 'daemon off;' & NGINX_PID=$! wait -n "$BACKEND_PID" "$FRONTEND_PID" "$NGINX_PID"