> Markdown export: /developers/environment-variables.md
> HTML: /developers/environment-variables
---
description: Canonical environment variable reference for self-hosted Eigen Mesh deployments.
audience: operator
---

# Environment variables

> **In plain terms:** These settings tell a self-hosted Eigen Mesh deployment how to connect to its database, encrypt data, and call the LLM gateway — set them in `.env` before starting Docker.

Set these in `.env` at the root of the **[eigen repository](https://github.com/your-org/eigen)** or in your hosting dashboard (Coolify, etc.). Compose passes `DATABASE_URL`, `AGE_GRAPH_NAME`, `HOST`, and `PORT` to the app container automatically.

::: warning
Variables marked as secrets (`BETTER_AUTH_SECRET`, `TENANT_MASTER_KEY`, API keys, OAuth client secrets) must not be committed to version control. Change default passwords before production.
:::

## Who this is for

- **Operators** configuring a self-hosted Docker deployment
- **Contributors** looking up canonical variable names and defaults

## Non-negotiable (app fails without these)

| Variable | Purpose | How to set |
|----------|---------|------------|
| `BETTER_AUTH_SECRET` | Session encryption | `openssl rand -base64 32` |
| `TENANT_MASTER_KEY` | Per-tenant envelope encryption | `openssl rand -base64 32` — see [Tenant envelope encryption](/developers/tenant-envelope-encryption) |
| `AGE_GRAPH_NAME` | Apache AGE graph name (must match Postgres init) | `eigen_graph` (default) |
| `ORIGIN` | Public URL for users and OAuth callbacks | e.g. `https://eigen.example.com` |

## Database

| Variable | Default | Purpose |
|----------|---------|---------|
| `DATABASE_URL` | `postgres://eigen:eigen@db:5432/eigen` | App connection string |
| `DATABASE_ADMIN_URL` | Same as above | Migrations, RLS, pg_cron (superuser) |
| `POSTGRES_PASSWORD` | `eigen` | DB password — **change in production** |
| `EIGEN_APP_DB_PASSWORD` | — | Password for RLS role `eigen_app` |

## LLM gateway — platform credits path

Users top up via PayPal; the app uses operator service keys.

| Variable | Purpose |
|----------|---------|
| `SERVICE_API_KEY_EUROUTER` | EUrouter service key |
| `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) |
| `OPENROUTER_BASE_URL` | e.g. `https://openrouter.ai/api/v1` |

## LLM gateway — BYOK fallback

Used when users supply keys in Settings → LLM → BYOK, or as env fallbacks:

| Variable | Purpose |
|----------|---------|
| `LLM_API_KEY` | EUrouter API key fallback |
| `OPENROUTER_API_KEY` | OpenRouter API key fallback |

## PayPal (platform credits)

| Variable | Purpose |
|----------|---------|
| `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 |

Omit PayPal vars if all users use BYOK only.

## Consolidation (nightly sleep)

| Variable | Required | Purpose |
|----------|----------|---------|
| `ADMIN_CONSOLIDATION_KEY` | Yes (for cron) | `X-Admin-Key` on consolidate endpoint — `openssl rand -hex 32` |
| `CONSOLIDATION_INTERNAL_URL` | Yes (compose) | App URL from DB network, e.g. `http://app:3000` |
| `CONSOLIDATION_CRON_SCHEDULE` | No | Cron expression (default `0 2 * * *`) |
| `CONSOLIDATION_CRON_TZ` | No | Timezone (default UTC) |

## OAuth (optional)

| Variable | Purpose |
|----------|---------|
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | Google sign-in — callback `{ORIGIN}/api/auth/callback/google` |
| `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` | GitHub sign-in — callback `{ORIGIN}/api/auth/callback/github` |

## Push notifications (optional)

| Variable | Purpose |
|----------|---------|
| `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT` | Web push — `npx web-push generate-vapid-keys` |

## Admin bootstrap (optional)

| Variable | Purpose |
|----------|---------|
| `ADMIN_NAME`, `ADMIN_EMAIL`, `ADMIN_PASSWORD` | Create first admin on container start |

## Tuning (optional)

| Variable | Default | Purpose |
|----------|---------|---------|
| `LLM_MIN_REQUEST_INTERVAL_MS` | `1000` | Global LLM throttle |
| `EMBEDDING_COMPRESS_INTENSITY` | — | `lite` \| `full` \| `ultra` |

## Next steps

- [What is Eigen Mesh?](/developers/what-is-eigenmesh)
- [Overview & quick start](/developers/getting-started)
- [Onboarding (managed)](/developers/onboarding-managed) — managed sign-up
- [Self-hosted setup](/developers/self-hosted-setup) — operator provisioning
- [Troubleshooting](/developers/troubleshooting)
