# ═══════════════════════════════════════════════════════════════ # openvibe.bot — Environment Configuration # Copy to .env for development. In production this lives at /etc/openvibe/bot.env (0600). # Names only here; never commit a value. # ═══════════════════════════════════════════════════════════════ # Server PORT=4630 HOST=127.0.0.1 NODE_ENV=development BASE_URL=http://localhost:4630 TRUST_PROXY=1 # ── Data: PostgreSQL + Valkey (ADR-035) ────────────────────── # In production OpenVibe.Host writes all four (roles/data/add-service.sh bot). Unset in development: # an embedded PGlite database in data/pglite (one process). Tests need neither. DATABASE_URL= DATABASE_DIRECT_URL= VALKEY_URL= VALKEY_PREFIX=ov:bot: # ── Identity: OpenVibe.Network ────────────────────────────── OV_NETWORK_URL=https://openvibe.network OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 #OV_NETWORK_ISSUER=https://openvibe.network # Optional: pin the Network's RS256 public key (PEM, \n escaped) instead of fetching the JWKS. #OV_NETWORK_PUBLIC_KEY= # Audience Bot accepts on incoming service tokens. BOT_AUDIENCE=openvibe.bot OV_OAUTH_CLIENT_ID=bot OV_OAUTH_CLIENT_SECRET= #OV_OAUTH_REDIRECT_URI=https://openvibe.bot/auth/callback #COOKIE_SECURE=true # ── OpenVibe.Events ───────────────────────────────────────── # Relay of Bot's outbox (bot.*); off when unset (rows wait in bot_event_outbox). #EVENTS_URL=http://127.0.0.1:4300 # OpenVibe.Events → Bot (ADR-033 account export and deletion): signs a delivery to POST /internal/events # (comma-separated for rotation, 32+ characters each). Unset: the route answers 503 and no subscription is created. #BOT_EVENTS_SECRET= #EVENTS_RELAY_INTERVAL_MS=2000 # ── Pairing and device link (ADR-043) ─────────────────────── # Who mints pairing codes: bot (the default) or network. Any other value refuses to boot. #BOT_PAIRING_AUTHORITY=bot #BOT_PAIRING_TTL_MS=600000 #BOT_PAIRING_MAX_TRIES=5 #BOT_HEARTBEAT_MS=1000 # A person's input on a machine's screen holds it for them this long; an agent's input there is refused meanwhile (ms). #BOT_PERSON_TURN_MS=15000 # Vibe by voice (server/voice.js): OpenVibe.Chat's loopback origin (empty turns voice off) and questions a machine an hour. #BOT_CHAT_INTERNAL_URL=http://127.0.0.1:4400 #BOT_VOICE_PER_HOUR=30 #BOT_OFFLINE_MISSES=2 #BOT_OFFLINE_GRACE_MS=3000 #BOT_ROTATE_GRACE_MS=60000 #BOT_NODE_REAUTH_MS=330000 # ── Control ───────────────────────────────────────────────── #BOT_MAX_COMMAND_MS=300 #BOT_HOLD_RESEND_MS=150 #BOT_TELEMETRY_HZ=2 #BOT_QUEUE_TURN_MS=60000 #BOT_QUEUE_TURN_BUDGET=50 #BOT_CONTROL_COOLDOWN_MS=0 # ── Limits / jobs / installer ─────────────────────────────── #BOT_LIMITS_MINUTE=120 #BOT_LIMITS_HOUR=3000 #BOT_JOBS=on #BOT_JOBS_INTERVAL_MS=5000 #BOT_INSTALLER_URL=https://openvibe.link/install # Where GET /install redirects (302): OpenVibe Link's installer script. Defaults to the checksummed asset on # OpenVibe Link's latest release (install.sh, pinned there by its CI cmp guard so it never drifts with main). # https on raw.githubusercontent.com, github.com, objects.githubusercontent.com or openvibe.bot only; anything # else refuses to boot. #BOT_INSTALLER_SOURCE_URL=https://github.com/OpenVibers/OpenVibe.Link/releases/latest/download/install.sh # The WHIP ingest base each device publishes to; whip_url = /. Unset or empty: pair without video. # In production this is OpenRestream's WHIP ingest, https://ingest.openre.stream/whip (O30); the key must be one # OpenRestream issued (BOT_OPENRE_* below), or the ingest refuses the device. #BOT_WHIP_BASE=https://example.invalid/whip # OpenRestream, which issues each robot's publish key (its stream's ingest key). Bot mints its own Network # service token (audience openvibe.openre) from OV_OAUTH_CLIENT_ID/SECRET and OV_NETWORK_INTERNAL_URL, holding # openre.stream.read, openre.stream.write, openre.key.rotate and openre.session.read/openre.output.read/ # openre.output.write (session and outputs, for panel video and restreaming). BOT_OPENRE_TOKEN overrides it # with an operator-minted service token of the same grant. BOT_OPENRE_URL unset: devices pair without video. #BOT_OPENRE_URL= #BOT_OPENRE_TOKEN= #BOT_OPENRE_TIMEOUT_MS=8000 # ── Server-side ONVIF cameras (camera.onvif) ──────────────── # A JSON object keyed by robot id (or "*" for any ONVIF-profile robot) → its camera's ONVIF PTZ service. # Bot connects server-side, writes a kind server device row and translates ptz commands to ONVIF; the profile # carries no host or credential. username_ref/password_ref name the environment variables (or secret-store # keys) holding the ONVIF user and password; the values are read per request and never stored or logged. The # URL must be http(s), on one host, with no embedded credentials, or Bot refuses to boot. #BOT_ONVIF_CAMERAS={"rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X":{"url":"http://192.168.1.50/onvif/ptz_service","username_ref":"CAM_USER","password_ref":"CAM_PASSWORD"}} #BOT_ONVIF_TIMEOUT_MS=5000 # ── OpenVibe.Billing: job usage (plan T14 L1) ─────────────── # Where the per-second readings of jobs run on paired Links go: billing.usage.record, POST /api/v1/usage. # Bot mints its own Network service token (audience openvibe.billing, capability billing.usage.record) from # OV_OAUTH_CLIENT_ID/SECRET and OV_NETWORK_INTERNAL_URL; BOT_BILLING_TOKEN, an operator-minted service token of # the same grant, overrides it. BOT_BILLING_URL unset: readings wait in run_usage_outbox (never dropped) and a # later relay delivers each once. #BOT_BILLING_URL=http://127.0.0.1:4600 #BOT_BILLING_TOKEN= #BOT_BILLING_INTERVAL_MS=2000 #BOT_BILLING_TIMEOUT_MS=5000 # ── OpenVibe.AI: the models on people's machines (ai-metrics.md) ─ # Every `ai` command's answer is one ai.call-report@1 to AI's POST /api/v1/usage/calls, so the local models on # a person's machine are in the same meter as every other AI call. Bot mints its own Network service token (audience # openvibe.ai, capability ai.usage.report) from OV_OAUTH_CLIENT_ID/SECRET and OV_NETWORK_INTERNAL_URL. Unset (or no # client secret): metering is off and an ai command's answer is unchanged. #OV_AI_INTERNAL_URL=http://127.0.0.1:4700 # ── Embeddable panel (plan T15 R9) ────────────────────────── # Pages that may frame a robot's read-only panel (CSP frame-ancestors), comma or space separated. Each entry is a # bare https origin (no path, query or wildcard); http://localhost: is accepted outside production only. # An invalid entry stops the service at boot. Default: OpenVibe.Live. A robot is embeddable only after its owner # turns on "embed_public" on its panel. The embedding page must also allow Bot's origin (BASE_URL, https://openvibe.bot) # in its own CSP frame-src, or the browser refuses the frame. #BOT_EMBED_ORIGINS=https://openvibe.live,https://www.openvibe.live # The anonymous read-only /watch socket behind the embed: open sockets per client address and watchers per robot. #BOT_WATCH_MAX_PER_IP=20 #BOT_WATCH_MAX_PER_ROBOT=500 # OpenVibe Link for Android: the published download (the signed release APK), https on GitHub releases or openvibe.link. # Unset until the owner's release key exists: /link/phone then says the app is in testing and mints no code. # LINK_ANDROID_APK_URL=https://github.com/OpenVibers/OpenVibe.Link/releases/download/vX.Y.Z/openvibe-link.apk