Skip to content

Configuration

Botmem is configured through environment variables. All variables have sensible defaults for local development, except DATABASE_URL which is required.

Environment Variables

Core Infrastructure

VariableDefaultDescription
PORT12412API server port
DATABASE_URL(required)PostgreSQL connection string (e.g. postgresql://botmem:botmem@localhost:5432/botmem)
REDIS_URLredis://localhost:6379Redis connection URL for BullMQ job queues
APP_URL(same as FRONTEND_URL)Public app URL used for login, reset, billing, CLI login, and connector return links
LANDING_URL(same as APP_URL)Public marketing URL used in OAuth metadata
BASE_URL(same as FRONTEND_URL)Public API/OAuth issuer URL, e.g. https://api.botmem.xyz
FRONTEND_URLhttp://localhost:12412Comma-separated browser origins allowed by CORS
PLUGINS_DIR./pluginsDirectory for external connector plugins
LOGS_PATH./data/logs.ndjsonPath for NDJSON log file output

AI Backend

Botmem supports two AI backends — Ollama (local, default) and OpenRouter (cloud API). Set AI_BACKEND to switch between them.

VariableDefaultDescription
AI_BACKENDollamaAI backend: ollama or openrouter
EMBED_DIMENSION(auto)Embedding vector dimension (auto-detected from model; 768 for nomic, 1024 for mxbai, 3072 for Gemini)

Ollama (default)

VariableDefaultDescription
OLLAMA_BASE_URLhttp://localhost:11434Ollama API base URL
OLLAMA_EMBED_MODELmxbai-embed-largeEmbedding model (1024 dimensions)
OLLAMA_TEXT_MODELqwen3:8bText enrichment + entity extraction (uses /no_think mode)
OLLAMA_VL_MODELqwen3-vl:4bVision-language model for photo/file analysis
OLLAMA_USERNAME(empty)Basic auth username for Ollama (optional)
OLLAMA_PASSWORD(empty)Basic auth password for Ollama (optional)

OpenRouter (cloud)

VariableDefaultDescription
OPENROUTER_API_KEY(empty)OpenRouter API key (required if AI_BACKEND=openrouter)
OPENROUTER_EMBED_MODELgoogle/gemini-embedding-001Embedding model (3072 dimensions)
OPENROUTER_TEXT_MODELmistralai/mistral-nemoText enrichment model
OPENROUTER_VL_MODELgoogle/gemma-3-4b-itVision-language model

OpenRouter dimensions

When using OpenRouter with Gemini embeddings, set EMBED_DIMENSION=3072 to match the model's output.

Authentication

VariableDefaultDescription
AUTH_PROVIDERlocalAuth provider: local (JWT) or firebase
JWT_ACCESS_SECRETdev-access-secret-change-in-productionJWT access token signing secret
JWT_REFRESH_SECRETdev-refresh-secret-change-in-productionJWT refresh token signing secret
JWT_ACCESS_EXPIRES_IN15mAccess token expiry
JWT_REFRESH_EXPIRES_IN7dRefresh token expiry
OAUTH_JWT_SECRETdev-oauth-jwt-secret-change-in-productionSecret for OAuth state tokens

Firebase (optional)

VariableDefaultDescription
FIREBASE_PROJECT_IDbotmem-appFirebase project ID
FIREBASE_SERVICE_ACCOUNT(empty)Service account JSON string (required on non-GCP servers)
GMAIL_CLIENT_ID(empty)Server-side Gmail OAuth client ID (Firebase mode)
GMAIL_CLIENT_SECRET(empty)Server-side Gmail OAuth client secret (Firebase mode)

Encryption

VariableDefaultDescription
APP_SECRETdev-app-secret-change-in-productionAES-256-GCM key for encrypting credentials at rest

Production secrets

For public-facing deployments, you must change APP_SECRET, JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, and OAUTH_JWT_SECRET from their defaults. Generate secure secrets with: openssl rand -base64 48

The server logs Using default dev secrets (OK for local/self-hosted) when defaults are detected. For actual production deployments (Stripe configured or PRODUCTION_DEPLOY=true), the server will refuse to start with default secrets.

Billing (Managed tier only)

VariableDefaultDescription
STRIPE_SECRET_KEY(empty)Stripe secret key (empty = self-hosted mode)
STRIPE_WEBHOOK_SECRET(empty)Stripe webhook signing secret
STRIPE_PRO_PRICE_ID(empty)Stripe price ID for Pro plan

When STRIPE_SECRET_KEY is empty, the app runs in self-hosted mode with no billing features and no memory quotas (unlimited).

In cloud mode (Stripe configured), free-plan users are limited to 500 memories total across all connectors. Pro subscribers get unlimited memories. Search always works regardless of plan.

Email (optional)

VariableDefaultDescription
SMTP_HOST(empty)SMTP server host (empty = email disabled)
SMTP_PORT587SMTP server port
SMTP_USER(empty)SMTP username
SMTP_PASS(empty)SMTP password
SMTP_FROM(SMTP_USER or [email protected])Sender email address

Analytics (optional)

VariableDefaultDescription
POSTHOG_API_KEY(empty)PostHog project API key
POSTHOG_HOSThttps://us.i.posthog.comPostHog ingestion host
VariableDefaultDescription
OPENAI_API_KEY(empty)OpenAI API key for PostgreSQL search index conversation model (gpt-4.1-nano). Optional — conversation search is skipped when not set.

One-Shot Legacy Search Drain

These are only for the first startup while a legacy Typesense service is still reachable. When DRAIN_TYPESENSE_TO_PG_ON_STARTUP=1, the API bootstrap runs apps/api/scripts/drain-typesense-to-pg-search.js after database migrations and before listening for traffic. The script exports every document from the legacy memories collection, upserts it into memory_search_index, deletes each document from Typesense only after its Postgres write commits, and records completion in the system_startup_tasks table so restarts skip it.

VariableDefaultDescription
DRAIN_TYPESENSE_TO_PG_ON_STARTUP0Set to 1 for the first startup that should drain Typesense
LEGACY_TYPESENSE_URLhttp://typesense:8108Legacy Typesense URL
LEGACY_TYPESENSE_API_KEYbotmem-ts-keyLegacy Typesense API key
LEGACY_TYPESENSE_COLLECTIONmemoriesLegacy collection to export and delete from
TYPESENSE_DRAIN_BATCH_SIZE1Documents processed per database transaction
TYPESENSE_DRAIN_DELETE_ORPHANS0Set to 1 to delete legacy docs whose memory row is missing

Other

VariableDefaultDescription
SYNC_DEBUG_LIMIT0Max events per sync (0 = unlimited full sync; set to e.g. 500 for dev)
DECAY_CRON0 3 * * *Cron schedule for recency weight decay (daily at 3am)

Docker Compose

The included docker-compose.yml starts all infrastructure services:

yaml
services:
  postgres:
    image: postgres:17-alpine
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: botmem
      POSTGRES_PASSWORD: botmem
      POSTGRES_DB: botmem
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:7.4-alpine
    ports:
      - '6379:6379'
    command: redis-server --appendonly yes --appendfsync everysec
    volumes:
      - redis-data:/data

  # Optional: local Ollama instance
  ollama:
    image: ollama/ollama:0.6.2
    profiles: [ollama]
    ports:
      - '11434:11434'
    volumes:
      - ollama-data:/root/.ollama

To start optional services, use Docker Compose profiles:

bash
# Core services only (PostgreSQL + pgvector + Redis)
docker compose up -d

# Include local Ollama
docker compose --profile ollama up -d

Ollama can also run separately — either locally or on a dedicated GPU machine. Set OLLAMA_BASE_URL to point to wherever your Ollama instance lives.

Example .env File

bash
# Infrastructure (DATABASE_URL is required)
DATABASE_URL=postgresql://botmem:botmem@localhost:5432/botmem
PORT=12412
REDIS_URL=redis://localhost:6379
DATABASE_URL=http://localhost:8108

# AI Backend (choose one)
AI_BACKEND=ollama
OLLAMA_BASE_URL=http://192.168.1.100:11434
OLLAMA_EMBED_MODEL=mxbai-embed-large
OLLAMA_TEXT_MODEL=qwen3:8b
OLLAMA_VL_MODEL=qwen3-vl:4b

# Or use OpenRouter instead:
# AI_BACKEND=openrouter
# OPENROUTER_API_KEY=sk-or-...
# EMBED_DIMENSION=3072

# Auth (defaults are fine for local dev — MUST change in production)
# JWT_ACCESS_SECRET=change-me-in-production
# JWT_REFRESH_SECRET=change-me-in-production
# OAUTH_JWT_SECRET=change-me-in-production

# Encryption
# APP_SECRET=change-me-in-production

# Frontend
APP_URL=http://localhost:12412
BASE_URL=http://localhost:12412
FRONTEND_URL=http://localhost:12412

Required AI Models

Ollama (default backend)

Before starting Botmem, pull the required models on your Ollama host:

bash
ollama pull mxbai-embed-large    # Embeddings (1024 dimensions, cosine similarity)
ollama pull qwen3:8b             # Text enrichment, entity extraction, factuality
ollama pull qwen3-vl:4b          # Vision-language for photo descriptions

The embed model produces 1024-dimensional vectors. PostgreSQL search index auto-creates the collection on first use with the correct dimensionality.

OpenRouter (cloud backend)

No model downloads needed. Set your API key and the default models will be used:

  • google/gemini-embedding-001 — embeddings (3072 dimensions)
  • mistralai/mistral-nemo — text enrichment
  • google/gemma-3-4b-it — vision-language

Network Requirements

Botmem needs to reach:

  • PostgreSQL on DATABASE_URL (default: localhost:5432)
  • Redis on REDIS_URL (default: localhost:6379)
  • PostgreSQL search index on DATABASE_URL (default: localhost:8108)
  • Ollama on OLLAMA_BASE_URL (or OpenRouter API if using cloud backend)
  • External APIs for each connector (Gmail API, Slack API, etc.)

Your memories. Your agents. Your control.