# ═══════════════════════════════════════════════════════════════ # OpenVibe.Search — Environment Configuration # Copy to .env and fill in values. # In production this lives at /etc/openvibe/search.env (0600); the systemd unit sets # NODE_ENV and PORT itself. # ═══════════════════════════════════════════════════════════════ # Server PORT=4710 HOST=127.0.0.1 NODE_ENV=development #BASE_URL=https://search.openvibe.network # Identity — OpenVibe.Network signs service tokens (client_credentials, audience # openvibe.search) and user JWTs. The keys come from the SDK's JWKS client # (openvibe-sdk/auth) at /api/.well-known/jwks: one # refresher, last good keys through an outage, a rotation honoured at once. OV_NETWORK_URL=https://openvibe.network OV_NETWORK_INTERNAL_URL=http://127.0.0.1:4000 #OV_NETWORK_ISSUER=https://openvibe.network # A browser's user JWT is accepted when its aud contains one of these. #SEARCH_USER_AUDIENCES=openvibe.search,openvibe.network # This service's own principal (svc:search) — publishes search.document.* to Events # (events.event.publish) and creates its subscription (events.subscription.manage); with # SEARCH_SAVED_NOTIFY=1 also resolves people and pushes notifications on Network. OV_OAUTH_CLIENT_ID=search OV_OAUTH_CLIENT_SECRET= # Store (PostgreSQL, ADR-035), written by OpenVibe.Host roles/data/add-service.sh search: 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= # OpenVibe.Events. The outbox relay runs only when EVENTS_URL is set. #EVENTS_URL=http://127.0.0.1:4300 #EVENTS_RELAY_INTERVAL_MS=2000 # Signing secret(s) of the index-document subscription (comma-separated during rotation). # Generate before `npm run subscribe`, e.g. `openssl rand -hex 32`. Unset = webhook off (503). #SEARCH_EVENTS_SECRET= # Sources whose .index_document.* events are accepted (default: wiki blog news reviews # deals coupons trade community live media codes games tools sources). #SEARCH_EVENT_OWNERS=wiki,blog,news # Largest accepted request body (direct PUT and deliveries), bytes. #SEARCH_MAX_BODY_BYTES=262144 # Ranking: freshness weighting of full-text relevance (README "Ranking"). # score = relevance × (1 + WEIGHT × 2^(−age_days / HALF_LIFE_DAYS)); age from published_at, else # updated_at. WEIGHT 0 turns it off. #SEARCH_FRESHNESS_WEIGHT=1 #SEARCH_FRESHNESS_HALF_LIFE_DAYS=30 # Search Fabric (README "Search Fabric"): the web ladder through OpenVibe.AI. # AI's internal origin; unset uses the AI manifest's internalOrigin. Needs OV_OAUTH_CLIENT_SECRET above. #OV_AI_INTERNAL_URL=http://127.0.0.1:4700 # off leaves the paid/free web providers off; the open index and cached answers still answer. #SEARCH_WEB=on # Paid DeepSeek calls per day across all callers; past it the provider stands down. #SEARCH_WEB_DAILY=500 # Owners whose documents the ladder's own open index reads first. #SEARCH_OPEN_INDEX_OWNERS=sources # Semantic ranking (SF-2, README "Semantic ranking"): every public document gets one local # `bge-small-en-v1.5` embedding (384 dimensions) through OpenVibe.AI's POST /api/v1/embed, and a # query's keyword and vector ranks are fused with reciprocal rank fusion (k = 60). AI must serve # the embedding through its local provider (AI_LOCAL_EMBED_MODEL=bge-small-en-v1.5) and Network must # grant this principal `ai.run.create` with namespace `ai.embed` for audience openvibe.ai. # The job is on unless SEARCH_EMBED=0. At most SEARCH_EMBED_PER_MIN documents are embedded per # rolling minute (batches of 32); SEARCH_EMBED_INTERVAL_MS is how often a pass starts. #SEARCH_EMBED=1 #SEARCH_EMBED_MODEL=bge-small-en-v1.5 #SEARCH_EMBED_DIM=384 #SEARCH_EMBED_PER_MIN=120 #SEARCH_EMBED_INTERVAL_MS=60000 # Restore-drill mode: background work stays off (the drill also blanks OV_OAUTH_CLIENT_SECRET). #SEARCH_DRILL=1 # Code search (server/code): GET /api/v1/search/code merges public code from GitHub, Sourcegraph and # our own forge. Keys stay server-side; the owner console at /console/code-sources shows the variable # name and whether it is set, never the value. SEARCH_CODE=off turns the public route off. #GITHUB_CODE_TOKEN= # required for GitHub; 10 API requests/minute #SOURCEGRAPH_TOKEN= # optional; Sourcegraph Cloud answers public searches without one #FORGE_TOKEN= # optional; only needed if the forge starts requiring auth #FORGE_CODE_REPOS= # optional owner/repo list; default: newest pushed public repos #SEARCH_CODE_TIMEOUT_MS=8000 #SEARCH_CODE_CACHE_MS=60000 #SEARCH_FORGE_MAX_REPOS=20 #SEARCH_GITHUB_PER_MINUTE=10 #SEARCH_SOURCEGRAPH_PER_MINUTE=30 #SEARCH_FORGE_PER_MINUTE=60 # Deep mode: POST /api/v1/search/code/deep, signed in; two ai.complete runs (rewrite + answer) through # OpenVibe.AI, which is the metered AI path. SEARCH_CODE_DEEP=off hides it; the budget caps are hard. #SEARCH_CODE_DEEP=1 #SEARCH_CODE_AI_URL=http://127.0.0.1:4700 #SEARCH_CODE_DEEP_QUERIES=4 #SEARCH_CODE_DEEP_FILES=6 #SEARCH_CODE_DEEP_CHARS=24000 #SEARCH_CODE_DEEP_TOKENS=800 #SEARCH_CODE_DEEP_WAIT_MS=25000 #SEARCH_CODE_DEEP_TIMEOUT_MS=120000 # Saved searches per signed-in person. #SEARCH_SAVED_MAX_PER_SUBJECT=50 # Notifications of new matches through OpenVibe.Network (README "Saved searches"): off unless 1, and # then only with OV_OAUTH_CLIENT_SECRET above. Network must grant the principal `search` # network.notifications.push (own service `search`) and identity.subject.resolve. #SEARCH_SAVED_NOTIFY=1 #SEARCH_SAVED_NOTIFY_INTERVAL_MS=900000 #SEARCH_SAVED_NOTIFY_BATCH=100 # Per-actor limits (server/actor-limits.js): requests one caller (a service principal, a signed-in # person, else an address) may make to a read route per minute and per hour; past them 429 # rate_limited with Retry-After. Indexing, suggest and saved-search changes have their own (README). #SEARCH_LIMITS_MINUTE=120 #SEARCH_LIMITS_HOUR=3000 # IndexNow (openvibe-shared/indexnow): Search publishes no pages of its own to submit, so only the # key file is served, at /.txt, when INDEXNOW_KEY is set. Unset: off (nothing mounted, nothing sent). #INDEXNOW_KEY= # Removal purge queue (README "Removals, caches and the CDN"). Every removal is recorded for # its owner (GET /api/v1/owners/:owner/removals). The Cloudflare purge of a formerly public URL # runs only when CLOUDFLARE_PURGE_TOKEN is set (inert otherwise). The token needs only # Zone → Cache Purge → Purge on the zones below. Never commit it: /etc/openvibe/search.env (0600). #CLOUDFLARE_PURGE_TOKEN= # host=zone id pairs; a URL uses the zone of its host or nearest parent domain. #CLOUDFLARE_ZONE_IDS=openvibe.wiki=,openvibe.blog=,openvibe.network= # Paths on the removed URL's host purged with it (default /sitemap.xml; `none` for none). #CLOUDFLARE_PURGE_RELATED_PATHS=/sitemap.xml,/feed.atom,/feed.json #CLOUDFLARE_PURGE_INTERVAL_MS=5000