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.
Recommended for production
| 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
Clone and configure
git clone https://github.com/your-org/eigen.git && cd eigen cp .env.example .env # Edit .env — set required variables aboveStart the stack
docker compose up -d --buildApply 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:rlsOptional: bootstrap an admin user — set
ADMIN_NAME,ADMIN_EMAIL, andADMIN_PASSWORDin.envbefore starting the app container, or run:docker compose exec app node scripts/create-admin.mjsThe script is idempotent (skips if the email already exists). Admin users still see the welcome tour until they complete or skip onboarding.
Verify — open
ORIGINin 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
- Overview & quick start — Docker Compose commands and Coolify notes
- Environment variables — full reference
- Deployment model — ownership and licensing philosophy