Configuration

All environment variables · ~10 min read v1.0

Overview

All xbrain services are configured via environment variables defined in infrastructure/.env. This file is gitignored — it is never committed to the repository. An .env.example is provided with safe defaults and CHANGE_ME placeholders for all secrets.

Never Commit .env

The infrastructure/.env file contains real secrets. It is gitignored by design. Only infrastructure/.env.example (with placeholder values) is tracked in git. Never commit your actual .env to the repository.

bashcp infrastructure/.env.example infrastructure/.env
# Edit .env and replace all CHANGE_ME values with your actual credentials

Core Database

PostgreSQL is the primary relational store for memory-api, events, audit logs, and team/user data. These variables are required on all phases.

Variable Required Default Description
POSTGRES_USER Yes xbrain PostgreSQL username
POSTGRES_PASSWORD Yes PostgreSQL password. Use a strong random value.
POSTGRES_DB Yes xbrain PostgreSQL database name
DATABASE_URL Yes Full async DSN: postgres+asyncpg://user:pass@postgres:5432/db

memory-api

memory-api is the central memory service — all read/write operations from LibreChat, Open WebUI, and agents go through it. Several variables are phase-gated (Phase 3+, Phase 5).

Variable Required Default Description
QDRANT_URL Yes http://qdrant:6333 Qdrant vector store URL (internal Docker DNS)
QDRANT_API_KEY No (empty) Qdrant API key — leave empty unless Qdrant auth is enabled
BRIDGE_SHARED_SECRET Yes 32-char hex secret shared between memory-api and all bridges. Must match across services. Generate: openssl rand -hex 32
JWT_ALGORITHM No HS256 JWT signing algorithm used for bridge token verification
LOG_LEVEL No INFO Logging verbosity: DEBUG, INFO, WARNING, ERROR
ADMIN_USER_SUBS No (empty) Comma-separated Google sub IDs of admin users (grants admin endpoints)
MEMORY_API_EXTERNAL_URL No https://api.yourdomain.com Public URL of memory-api — used to construct Drive webhook callback URLs
GOOGLE_CLIENT_ID Yes Google OAuth 2.0 client ID (from Google Cloud Console)
GOOGLE_CLIENT_SECRET No Google OAuth 2.0 client secret. Required if Drive sync is enabled (Phase 3+).
OAUTH_CREDENTIALS_ENCRYPTION_KEY No Fernet key for encrypting stored Drive OAuth tokens at rest. Required for Phase 3+. Generate: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
NEO4J_URI No bolt://neo4j:7687 Neo4j Bolt connection URI (Phase 3+)
NEO4J_USER No neo4j Neo4j username (Phase 3+)
NEO4J_PASSWORD No Neo4j password. Required when Neo4j is enabled (Phase 3+).
GRAPHITI_SERVICE_URL No http://graphiti-service:8300 Graphiti temporal extraction service URL. memory-api fails soft if unreachable (Phase 5).
GITHUB_ORG No excalibur-game GitHub Organization name — used to verify membership during GitHub Auth login (Phase 5)
GITHUB_API_PAT No GitHub Personal Access Token with read:org scope. Required for GitHub Auth (Phase 5).

LibreChat

LibreChat connects to AI model providers via API keys. At least one model key is required for the chat interface to function.

Variable Required Default Description
ANTHROPIC_API_KEY No Anthropic API key for Claude models (sk-ant-...)
OPENAI_API_KEY No OpenAI API key for GPT models (sk-...)
XAI_API_KEY No xAI API key for Grok models
MEILI_MASTER_KEY Yes MeiliSearch master key (32+ chars). Generate: openssl rand -hex 32
LIBRECHAT_MONGO_URI Yes MongoDB URI for LibreChat's conversation and user storage

Bridge & Pipeline

The LibreChat bridge and Open WebUI pipeline forward conversations to memory-api. BRIDGE_SHARED_SECRET must match the value set in memory-api.

Variable Required Default Description
MEMORY_API_URL No http://memory-api:8000 Internal URL of memory-api (Docker service name)
BRIDGE_DEFAULT_TEAM_SCOPE No default Default team_scope tag applied when user has no team assignment
BRIDGE_BACKFILL_FROM No startup Backfill strategy for existing conversations: startup (on restart) or never
PIPELINE_API_KEY Yes Open WebUI pipeline API key. Must match Open WebUI's pipeline settings. Generate: openssl rand -hex 32
PIPELINE_DEFAULT_TEAM_SCOPE No default Default team_scope for Open WebUI pipeline writes
AGENT_RUNTIME_URL No http://agent-runtime:9100 agent-runtime URL used by the Open WebUI pipeline for LangGraph tool calls

agent-runtime

agent-runtime hosts LangGraph agents and connects to the MCP gateway for tool access.

Variable Required Default Description
MCP_GATEWAY_URL No http://mcp-gateway:8080 MCP gateway URL for tool discovery and invocation
MCP_TOOL_CACHE_TTL_SECS No 300 Seconds to cache the MCP tool list before re-fetching from gateway

Langfuse (Phase 2)

Langfuse provides LLM observability — tracing, cost tracking, and prompt management. Keys are generated from the Langfuse UI after first boot.

Variable Required Default Description
LANGFUSE_PUBLIC_KEY No Langfuse project public key (from Langfuse UI → Settings → API Keys)
LANGFUSE_SECRET_KEY No Langfuse project secret key

LANGFUSE_HOST in docker-compose.yml

LANGFUSE_HOST is hardcoded to http://langfuse:3000 (internal Docker DNS) in docker-compose.yml. This bypasses Cloudflare for SDK calls — the SDK communicates directly with the Langfuse container. Do not change this to the public URL.

Graphiti (Phase 5)

Graphiti performs temporal fact extraction from conversations and builds an episodic knowledge graph. memory-api calls it asynchronously and fails soft if the service is unavailable.

Variable Required Default Description
GRAPHITI_SERVICE_URL No http://graphiti-service:8300 URL called by memory-api to submit conversation episodes. Fails soft if unreachable.
SEMAPHORE_LIMIT No 3 Max concurrent Graphiti requests. Keep at 3 for Tier 1 API rate limits (OpenAI/Anthropic).

Generating Secrets

Several variables require cryptographically random values. Use these commands to generate appropriate secrets for each:

bash — secret generation# Generate BRIDGE_SHARED_SECRET (32-byte hex)
openssl rand -hex 32

# Generate MEILI_MASTER_KEY (32-byte hex)
openssl rand -hex 32

# Generate PIPELINE_API_KEY (32-byte hex)
openssl rand -hex 32

# Generate NEO4J_PASSWORD (base64, 16-byte)
openssl rand -base64 16

# Generate OAUTH_CREDENTIALS_ENCRYPTION_KEY (Fernet key, required for Drive sync)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Rotating BRIDGE_SHARED_SECRET

If you rotate BRIDGE_SHARED_SECRET, you must update the value in every bridge and restart all services simultaneously. In-flight bridge JWTs signed with the old secret will be rejected. Coordinate rotation during a maintenance window. Secrets stored in .env must never be committed to git — add infrastructure/.env to .gitignore.

Complete .env.example

This is the full infrastructure/.env.example as shipped in the repository. Copy it to infrastructure/.env and replace every CHANGE_ME value before starting any services.

infrastructure/.env.example# ================================================================
# xbrain — Environment Variable Reference
# Copy to infrastructure/.env and fill in your values.
# NEVER commit infrastructure/.env to git.
# ================================================================

# === Core Database ===
POSTGRES_USER=xbrain
POSTGRES_PASSWORD=CHANGE_ME
POSTGRES_DB=xbrain
DATABASE_URL=postgres+asyncpg://xbrain:CHANGE_ME@postgres:5432/xbrain

# === Qdrant (Vector Store) ===
QDRANT_URL=http://qdrant:6333
QDRANT_API_KEY=

# === Google OAuth (Required for SSO) ===
GOOGLE_CLIENT_ID=CHANGE_ME.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=CHANGE_ME

# === Security ===
BRIDGE_SHARED_SECRET=CHANGE_ME_32HEX
JWT_ALGORITHM=HS256
ADMIN_USER_SUBS=

# === AI Models ===
ANTHROPIC_API_KEY=sk-ant-CHANGE_ME
OPENAI_API_KEY=sk-CHANGE_ME
XAI_API_KEY=

# === LibreChat ===
MEILI_MASTER_KEY=CHANGE_ME_32HEX
LIBRECHAT_MONGO_URI=mongodb://mongo:27017/librechat

# === Bridge & Pipeline ===
MEMORY_API_URL=http://memory-api:8000
BRIDGE_DEFAULT_TEAM_SCOPE=default
BRIDGE_BACKFILL_FROM=startup
PIPELINE_API_KEY=CHANGE_ME_32HEX
PIPELINE_DEFAULT_TEAM_SCOPE=default
AGENT_RUNTIME_URL=http://agent-runtime:9100

# === agent-runtime ===
MCP_GATEWAY_URL=http://mcp-gateway:8080
MCP_TOOL_CACHE_TTL_SECS=300

# === Langfuse (Phase 2 — generate from Langfuse UI after first boot) ===
LANGFUSE_PUBLIC_KEY=
LANGFUSE_SECRET_KEY=

# === Neo4j (Phase 3) ===
NEO4J_URI=bolt://neo4j:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=CHANGE_ME

# === Drive Sync Encryption (Phase 3) ===
OAUTH_CREDENTIALS_ENCRYPTION_KEY=

# === External URLs ===
MEMORY_API_EXTERNAL_URL=https://api.yourdomain.com

# === Logging ===
LOG_LEVEL=INFO

# === GitHub Auth (Phase 5) ===
GITHUB_ORG=your-github-org
GITHUB_API_PAT=

# === Graphiti (Phase 5) ===
GRAPHITI_SERVICE_URL=http://graphiti-service:8300
SEMAPHORE_LIMIT=3

Next Steps