For the complete documentation index, see /developers/llms.txt Markdown versions: append .md to any /developers/{slug} URL. Browse structure: /developers/sitemap.md This page: /developers/self-hosted-setup.md

Self-hosted setup

In plain terms: This page is for operators who deploy and run Eigen Mesh on their own infrastructure with Docker. End users on your instance still sign up through the normal app — your job is to provision the stack first.

Use this path when you deploy and operate Eigen on your own stack (Docker Compose). End users still go through the managed onboarding tour after they sign in; your job is to provision the stack, secrets, and optional payment/social integrations first.

See also Overview & quick start for Docker Compose commands and Coolify notes.

Accounts to create (operator)

Create only the accounts that match how you want billing and auth to work.

Account When you need it What it is used for
EUrouter Platform credits and/or EUrouter BYOK Gateway for chat + embeddings via routing rules (LLM_BASE_URL, SERVICE_API_KEY_EUROUTER, LLM_RULE_CHAT, LLM_RULE_EMBEDDING).
OpenRouter Platform credits, OpenRouter BYOK, and/or speech-to-text Gateway for chat, embeddings, and dictation STT (OPENROUTER_BASE_URL, SERVICE_API_KEY_OPENROUTER or OPENROUTER_API_KEY, optional LLM_MODEL_*).
PayPal Developer Wallet top-ups (platform credits) In-app credit purchases (PAYPAL_API_BASE, PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET). Omit if all users will use BYOK only.
Google Cloud OAuth client Optional social sign-in GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET — callback {ORIGIN}/api/auth/callback/google.
GitHub OAuth app Optional social sign-in GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET — callback {ORIGIN}/api/auth/callback/github.

You do not need separate accounts for Postgres, pgvector, or Apache AGE — those run inside the Compose stack.

Environment variables (operator)

Copy .env.example to .env in the eigen repository and set values before docker compose up. See the full Environment variables reference. Grouped by purpose:

Required — app will not run safely without these

Variable Purpose How to set
BETTER_AUTH_SECRET Session encryption openssl rand -base64 32
AGE_GRAPH_NAME Apache AGE graph name (must match Postgres init) eigen_graph (default)
ORIGIN Public URL users and OAuth callbacks use e.g. https://eigen.example.com
TENANT_MASTER_KEY Master key for per-tenant envelope encryption Strong random secret (see tenant encryption runbook)
DATABASE_URL App connection string Compose default: postgres://eigen:eigen@db:5432/eigen
DATABASE_ADMIN_URL Migrations, RLS, pg_cron Same superuser URL as above for self-hosted

Never commit .env or share TENANT_MASTER_KEY and BETTER_AUTH_SECRET. Rotating TENANT_MASTER_KEY without re-encryption breaks existing tenant data.

Required for LLM — at least one billing path must work

Option A — Platform credits (Eigen wallet, default user billing mode)

Users top up via PayPal; the app calls your service-account gateway keys.

Variable Purpose
SERVICE_API_KEY_EUROUTER EUrouter service key (platform billing)
LLM_BASE_URL EUrouter API origin (no trailing slash), e.g. https://api.eurouter.ai/v1
LLM_RULE_CHAT EUrouter routing rule UUID for chat
LLM_RULE_EMBEDDING EUrouter routing rule UUID for embeddings
SERVICE_API_KEY_OPENROUTER OpenRouter service key (if using OpenRouter as platform provider)
OPENROUTER_BASE_URL OpenRouter API origin, e.g. https://openrouter.ai/api/v1
PAYPAL_API_BASE https://api-m.sandbox.paypal.com (sandbox) or https://api-m.paypal.com (live)
PAYPAL_CLIENT_ID PayPal REST app client ID
PAYPAL_CLIENT_SECRET PayPal REST app secret

Option B — BYOK only (users supply keys in Settings → LLM → BYOK)

You may still set env fallbacks used when a user has not saved keys in the database:

Variable Purpose
LLM_BASE_URL EUrouter base URL
LLM_API_KEY EUrouter API key fallback
LLM_RULE_CHAT / LLM_RULE_EMBEDDING EUrouter rule UUIDs
OPENROUTER_BASE_URL OpenRouter base URL
OPENROUTER_API_KEY OpenRouter API key fallback

Users on BYOK must configure credentials in the UI (or rely on these env fallbacks) and set billing mode to Bring your own key in Settings.

Variable Purpose
POSTGRES_PASSWORD Strong DB password (change from default eigen)
EIGEN_APP_DB_PASSWORD Password for RLS app role eigen_app
ADMIN_CONSOLIDATION_KEY Secures nightly consolidation webhook (openssl rand -hex 32)
CONSOLIDATION_INTERNAL_URL URL Postgres/pg_cron uses to reach the app (Compose: http://app:3000)

Optional

Variable Purpose
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT Web push notifications (npx web-push generate-vapid-keys)
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET Google sign-in
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET GitHub sign-in
ADMIN_NAME, ADMIN_EMAIL, ADMIN_PASSWORD Bootstrap first admin on container start (see below)
LLM_MIN_REQUEST_INTERVAL_MS Global LLM throttle (default 1000 ms)
EMBEDDING_COMPRESS_INTENSITY Embedding payload compression (lite | full | ultra)

First-run deployment steps

  1. Clone and configure

    git clone https://github.com/your-org/eigen.git && cd eigen
    cp .env.example .env
    # Edit .env — set required variables above
    
  2. Start the stack

    docker compose up -d --build
    
  3. Apply schema and RLS (first deploy only; the production entrypoint runs migrations automatically on subsequent starts)

    npm install
    npm run db:push:force
    npm run db:rls
    
  4. Optional: bootstrap an admin user — set ADMIN_NAME, ADMIN_EMAIL, and ADMIN_PASSWORD in .env before starting the app container, or run:

    docker compose exec app node scripts/create-admin.mjs
    

    The script is idempotent (skips if the email already exists). Admin users still see the welcome tour until they complete or skip onboarding.

  5. Verify — open ORIGIN in a browser, sign up or sign in as admin, complete the welcome tour, and confirm LLM billing (Credits or BYOK) before test captures.

Self-hosted end-user sign-up

Users can open Get early access — self-hosted (/signup?plan=self-hosted). Like managed sign-up, the plan label is informational; behavior depends on how you configured env vars and PayPal/BYOK, not on the query parameter.

Direct them to:

  • Settings → LLM → Credits if you enabled platform credits and PayPal.
  • Settings → LLM → BYOK if they should use their own EUrouter or OpenRouter keys.

Quick reference: who configures what

Concern Managed (end user) Self-hosted (operator) Self-hosted (end user)
Docker / Postgres / AGE Eigen You
BETTER_AUTH_SECRET, TENANT_MASTER_KEY, ORIGIN Eigen You
Service gateway keys (SERVICE_API_KEY_*) Eigen You
PayPal (wallet top-ups) Eigen (if offered) You (optional) Pays via PayPal UI
Personal LLM keys Only if switching to BYOK BYOK tab in Settings
Welcome tour Yes Yes
Capture / Activity / Chat Yes Yes

Troubleshooting

See Troubleshooting for deployment, LLM, MCP, and encryption issues.

Next steps

Agent Instructions

This documentation is published for humans and AI agents. Prefer .md URLs for structured content.

  • Index: /developers/llms.txt
  • Full export: /developers/llms-full.txt
  • Sitemap: /developers/sitemap.md
  • Raw page: append `.md` to any /developers/{slug} URL
  • Example: GET /developers/mcp-overview.md

Dynamic `?ask=` and `?goal=` query on markdown URLs is planned — see docs/planning/10-docs-query-api-design.md.