# ═══════════════════════════════════════════════════════════════ # OpenVibe.Events — Environment Configuration # Copy to .env and fill in values. # In production this lives at /etc/openvibe/events.env (0600); the systemd unit sets # NODE_ENV and PORT itself. # ═══════════════════════════════════════════════════════════════ # Server PORT=4300 HOST=127.0.0.1 NODE_ENV=development # The API origin (plan T7): everything Events names about itself — Location headers, realtime URLs, # limits.json links, llms.txt/sitemap, the home's examples — uses it; defaults to https://openvibe.events # in production, to http://localhost:PORT otherwise. #BASE_URL=https://openvibe.events # The product origin; defaults to BASE_URL (openvibe.events is the API and product origin, plan T7). #EVENTS_SITE_URL=https://openvibe.events # IndexNow (openvibe-shared/indexnow): a key makes search engines recrawl the product home and its # crawl files when they change (a release). 8–128 hex/alphanumeric characters; the key file is served # at /.txt. Unset = off, no key file, nothing sent. #INDEXNOW_KEY= # Identity — OpenVibe.Network signs service tokens (client_credentials, audience # openvibe.events) and user JWTs. The public key is fetched from # /api/.well-known/jwks (internal URL first), retried every 30 s until it loads. OV_NETWORK_URL=https://openvibe.network OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 # Expected `iss` of every token (defaults to OV_NETWORK_URL). #OV_NETWORK_ISSUER=https://openvibe.network # Pin the key instead of fetching it (PEM; \n escapes allowed). #OV_NETWORK_PUBLIC_KEY= # A browser's user JWT is accepted when its aud contains one of these. #EVENTS_USER_AUDIENCES=openvibe.events,openvibe.network # PostgreSQL (ADR-035), written by OpenVibe.Host roles/data/add-service.sh events: the runtime role through PgBouncer, # the owner on a direct connection (migrations), and Valkey (shared limit counters). # Without DATABASE_URL, development uses an embedded PGlite database in data/pglite. DATABASE_URL= DATABASE_DIRECT_URL= VALKEY_URL= VALKEY_PREFIX= # Optional NATS (deploy/nats/nats-server.conf): nats-v1, cross-process SSE fan-out (the TOPIC carrier), and nats-js-v1, # JetStream (the STREAM carrier, needs nats-server -js). nats://[user:pass@]host:4222 on loopback or the private network; # unset, nothing connects and pg-v1/valkey-v1 carry TOPIC, pg-v1 STREAM. EVENTS_CARRIERS_DISABLED=nats-v1 or nats-js-v1 # rolls one back; NATS_JETSTREAM=off leaves nats-js-v1 out. #NATS_URL= #NATS_SUBJECT_PREFIX=ov.events. #NATS_JETSTREAM= #NATS_STREAM=OV_EVENTS_STREAM # Optional cloud queue (ADR-042 decision 5): cloud-v1, a QUEUE-only push carrier that POSTs { event_id, subscription_id } # as an SQS SendMessage to a CLOUD_QUEUE_URL endpoint, SigV4-signed (node:crypto, no dependency). Credentials may be # omitted for a local endpoint; CLOUD_QUEUE_PREFIX is an optional path prefix under the URL. Off unless the URL is set; # EVENTS_CARRIERS_DISABLED=cloud-v1 rolls it back and pg-v1/valkey-v1 carries QUEUE. Its rate card (rc-cloud-queue-v1) is # not written until the owner sets its price: unpriced, the planner never prefers it. #CLOUD_QUEUE_URL= #CLOUD_QUEUE_REGION=us-east-1 #CLOUD_QUEUE_PREFIX= #CLOUD_QUEUE_ACCESS_KEY= #CLOUD_QUEUE_SECRET_KEY= #EVENTS_CARRIERS=pg-v1,valkey-v1,nats-v1,nats-js-v1,cloud-v1 #EVENTS_CARRIERS_DISABLED= # Retention in tiers (ADR-042 decision 8; README "Retention: three tiers"). Hot events (and their deliveries) older # than this move to the replay tier (events_archive) at the hourly prune. EVENTS_RETENTION_DAYS=30 # Days (from receipt) an event stays readable from the replay tier: pulls, SSE resume and by-id reads; resuming from # before it yields a gap. 0 = no replay tier: old events are deleted, as before, and events_archive is emptied. EVENTS_REPLAY_RETENTION_DAYS=365 # The archive tier, operator only (node scripts/events-archive.js export|restore --month YYYY-MM): a local directory, # or an S3-compatible bucket when EVENTS_ARCHIVE_S3_BUCKET is set (path-style, https; SigV4, no dependency). #EVENTS_ARCHIVE_DIR=/var/lib/openvibe/events-archive #EVENTS_ARCHIVE_S3_ENDPOINT=https://s3.example.com #EVENTS_ARCHIVE_S3_BUCKET= #EVENTS_ARCHIVE_S3_REGION=us-east-1 #EVENTS_ARCHIVE_S3_ACCESS_KEY_ID= #EVENTS_ARCHIVE_S3_SECRET_ACCESS_KEY= #EVENTS_ARCHIVE_S3_PREFIX=events/ # Accepted event ids are remembered this long, so late re-publishes stay duplicates. EVENTS_RECEIPT_RETENTION_DAYS=90 #EVENTS_PRUNE_INTERVAL_MS=3600000 # Publishing #EVENTS_MAX_PAYLOAD_BYTES=65536 # A trace may carry this many hops before a publish is refused (events.loop_detected). #EVENTS_MAX_HOPS=8 # Which source may publish which event_type prefixes. JSON; replaces the default, which is # { "": ["."] } for live media network community chat openre billing tips vip # ai games tools codes host sources search wiki blog news reviews deals coupons trade bot. Every prefix # must start with "."; "app" and "app-*" are reserved for developer apps. #EVENTS_SOURCE_PREFIXES={"live":["live."],"media":["media."]} # Network-wide prefixes any first-party service may publish (default: provider., provider health # and capacity telemetry). Comma-separated; a prefix's first segment must not be a source. #EVENTS_SHARED_PREFIXES=provider. # Delivery worker #EVENTS_WORKER=on #EVENTS_WORKER_INTERVAL_MS=500 #EVENTS_MAX_INFLIGHT=20 # Of which developer-app deliveries may use at most (default: half of EVENTS_MAX_INFLIGHT) #EVENTS_APP_MAX_INFLIGHT=10 #EVENTS_DELIVERY_TIMEOUT_MS=10000 #EVENTS_MAX_ATTEMPTS=8 #EVENTS_BACKOFF_MS=1000,5000,30000,120000,600000,3600000 # /api/ready lists `dlq` as degraded (the service stays ready) above this many dead deliveries. #EVENTS_DLQ_DEGRADED_AT=100 #EVENTS_MAX_SUBSCRIPTIONS=100 # Hostnames a subscription endpoint may use (SSRF guard). `*.openvibe.*` = openvibe. # and its subdomains; IP literals only when listed exactly. #EVENTS_ENDPOINT_HOSTS=127.0.0.1,*.openvibe.* # Project usage (WS-N task 4): each closed hour of a developer project's publishing and webhook # deliveries becomes one events.usage.recorded event per capability and environment, delivered to # Network (the project dashboard on openvibe.services). off = nothing counted or sent. #EVENTS_USAGE=on #EVENTS_USAGE_FLUSH_MS=300000 # Billing readings (plan T5 step 14, docs/cutover-events-billing-readings.md): each closed hour's queue operations per # production project (metric queue-operation-64kb) become one platform.usage-sample@1 reading posted to Billing # (billing.usage.record; the Network client `events` needs that grant). 0 = off. Without the URL or the secret the # readings are stored and stay queued. #EVENTS_BILLING_INTERVAL_MS=0 #OV_BILLING_INTERNAL_URL=http://127.0.0.1:4600 #OV_OAUTH_CLIENT_ID=events #OV_OAUTH_CLIENT_SECRET= # The account export and deletion consumer (ADR-033): Events' own subscription to the two account topics, delivered # back to POST /internal/events. Unset: the route is off and the account events do not reach Events. The secret is 32 # characters or more; it is the one Events signs its own deliveries with. #EVENTS_EVENTS_URL=https://openvibe.events #EVENTS_EVENTS_SECRET= # GitHub webhooks in (AL5: server/github.js): the secret GitHub signs deliveries with (repo Settings → # Webhooks → the webhook's Secret; 16 characters or more, comma-separated while rotating). Unset: POST # /api/v1/in/github answers 404 and no github.* event is ever stored. #EVENTS_GITHUB_WEBHOOK_SECRET= #OV_BILLING_AUDIENCE=openvibe.billing #OV_BILLING_TIMEOUT_MS=10000 # Developer apps (events.app.publish|read|subscribe, ADR-014). App subscriptions must use public # https endpoints (no allow-list; checked at subscribe and delivery time). Quotas are per project # and environment; 0 turns a limit off. EVENTS_APPS=off disables the app paths. #EVENTS_APPS=on #EVENTS_APP_PUBLISH_PER_MINUTE=120 #EVENTS_APP_RETAINED_BYTES=52428800 #EVENTS_APP_MAX_SUBSCRIPTIONS=20 #EVENTS_APP_SANDBOX_PUBLISH_PER_MINUTE=30 #EVENTS_APP_SANDBOX_RETAINED_BYTES=5242880 #EVENTS_APP_SANDBOX_MAX_SUBSCRIPTIONS=5 #EVENTS_APP_SANDBOX_RETENTION_DAYS=7 # Per-actor limits (server/actor-limits.js): requests one principal (svc:…, app:app_…) may make to a # read route per minute and per hour; past them 429 rate_limited with Retry-After. Publishing, # subscriptions and replay have their own numbers (README). Never on health, ready, metrics. # EVENTS_LIMITS=off turns them all off (a rollback lever). #EVENTS_LIMITS=on #EVENTS_LIMITS_MINUTE=120 #EVENTS_LIMITS_HOUR=3000 # Realtime (SSE) gateway #REALTIME_MAX_CONNECTIONS=2000 #REALTIME_MAX_TOPICS=20 #REALTIME_HEARTBEAT_MS=25000 #REALTIME_REPLAY_MAX=1000 # A browser resuming with Last-Event-ID is replayed public events received this recently only # (0: none); older public events come as `event: gap` (reason public_window). Subject events # addressed to the viewer, and service viewers, keep the whole retention. #REALTIME_PUBLIC_REPLAY_SECONDS=300 # Signed-out browsers may receive public events. #REALTIME_ALLOW_ANONYMOUS=true # Exact extra CORS origins besides https://*.openvibe.* (development). #REALTIME_CORS_ORIGINS=http://localhost:3000