Self-hosted dashboard and admin auth (#4837)
Co-authored-by: kartik-mem0 <kartik.labhshetwar@mem0.ai>
This commit is contained in:
co-authored by
kartik-mem0
parent
15feaa8ac4
commit
db8ac61713
@@ -13,6 +13,10 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
- You plan to explore or debug endpoints through the built-in OpenAPI page at `/docs`.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
**First time self-hosting, or upgrading from a pre-1.x build?** Start at [Self-Hosted Setup](/open-source/setup). It walks through the stack, the setup wizard, and the upgrade path for deployments that relied on open endpoints or `ADMIN_API_KEY`. This page covers the API surface and auth modes only.
|
||||
</Warning>
|
||||
|
||||
<Warning>
|
||||
**OSS vs Platform API paths:** The self-hosted OSS server does **not** use the `/v1/` prefix. For example, the endpoint is `POST /memories`, not `POST /v1/memories/`. The [API Reference](/api-reference) documents the hosted platform at `api.mem0.ai` which uses `/v1/` paths — those do not apply to the OSS server.
|
||||
</Warning>
|
||||
@@ -26,7 +30,7 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
## Feature
|
||||
|
||||
- **CRUD endpoints:** Create, retrieve, search, update, delete, and reset memories by `user_id`, `agent_id`, or `run_id`.
|
||||
- **API key authentication:** Optionally secure all endpoints with a shared API key via the `X-API-Key` header.
|
||||
- **Authentication:** On by default. Dashboard sessions use JWTs; programmatic clients use per-user `X-API-Key` headers. Legacy `ADMIN_API_KEY` is still supported.
|
||||
- **Status health check:** Access base routes to confirm the server is online.
|
||||
- **OpenAPI explorer:** Visit `/docs` for interactive testing and schema reference.
|
||||
|
||||
@@ -40,51 +44,75 @@ The Mem0 REST API server exposes every OSS memory operation over HTTP. Run it al
|
||||
<Tab title="Steps">
|
||||
1. Create `server/.env` with your keys:
|
||||
|
||||
```bash
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
```
|
||||
```bash
|
||||
OPENAI_API_KEY=your-openai-api-key
|
||||
JWT_SECRET=$(openssl rand -base64 48)
|
||||
```
|
||||
|
||||
2. Start the stack:
|
||||
2. Bootstrap the stack in one command:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
docker compose up
|
||||
```
|
||||
```bash
|
||||
cd server
|
||||
make bootstrap # starts Compose, creates an admin, issues the first API key
|
||||
```
|
||||
|
||||
3. Reach the API at `http://localhost:8888`. Edits to the server or library auto-reload.
|
||||
Or to start the stack only and finish setup via the browser wizard at http://localhost:3000:
|
||||
|
||||
```bash
|
||||
cd server
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
3. API is at `http://localhost:8888`. Code edits auto-reload.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Run with Docker
|
||||
<AccordionGroup>
|
||||
<Accordion title="Other install paths">
|
||||
**Run with Docker**
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Pull image">
|
||||
<Tabs>
|
||||
<Tab title="Pull image">
|
||||
```bash
|
||||
docker pull mem0/mem0-api-server
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Build locally">
|
||||
</Tab>
|
||||
<Tab title="Build locally">
|
||||
```bash
|
||||
docker build -t mem0-api-server .
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
1. Create a `.env` file with `OPENAI_API_KEY`.
|
||||
2. Run the container:
|
||||
1. Create a `.env` file with `OPENAI_API_KEY` and `JWT_SECRET`.
|
||||
2. Run the container:
|
||||
|
||||
```bash
|
||||
docker run -p 8000:8000 --env-file .env mem0-api-server
|
||||
```
|
||||
```bash
|
||||
docker run -p 8000:8000 --env-file .env mem0-api-server
|
||||
```
|
||||
|
||||
3. Visit `http://localhost:8000`.
|
||||
3. Visit `http://localhost:8000`.
|
||||
|
||||
### Run directly (no Docker)
|
||||
**Run directly (no Docker)**
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
<Warning>
|
||||
This path skips Docker and assumes Postgres is already running and reachable at `POSTGRES_HOST:POSTGRES_PORT`. For a single-command local setup with Postgres included, use Docker Compose above.
|
||||
</Warning>
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Note>
|
||||
Compose publishes internal port 8000 as 8888 on the host. Raw Docker and raw uvicorn listen on 8000 unless remapped.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
`JWT_SECRET` is required once auth is enabled — the server returns `500` on auth endpoints if it's unset. Generate one with `openssl rand -base64 48`. See [Self-Hosted Setup](/open-source/setup#configure-the-environment) for the full env var table.
|
||||
</Note>
|
||||
|
||||
<Tip>
|
||||
Use a process manager such as `systemd`, Supervisor, or PM2 when deploying the FastAPI server for production resilience.
|
||||
@@ -98,35 +126,74 @@ uvicorn main:app --reload
|
||||
|
||||
## Authentication
|
||||
|
||||
The server supports optional API key authentication. When the `ADMIN_API_KEY` environment variable is set, every endpoint requires a valid `X-API-Key` header. The `/` redirect, `/docs`, and `/openapi.json` routes remain open so you can always reach the interactive API explorer.
|
||||
Auth is on by default. Protected endpoints require either a JWT (from the dashboard login flow) or an `X-API-Key` header. The `/` redirect, `/docs`, and `/openapi.json` routes stay open so you can reach the OpenAPI explorer.
|
||||
|
||||
| `ADMIN_API_KEY` value | Behavior |
|
||||
|---|---|
|
||||
| Not set / empty | All endpoints are open (no auth) |
|
||||
| Any non-empty string | Requests must include `X-API-Key: <your-key>` |
|
||||
| Mode | How to send it | When to use it |
|
||||
|---|---|---|
|
||||
| Bearer JWT | `Authorization: Bearer <access_token>` | Dashboard sessions; tokens come from `POST /auth/login` and refresh via `POST /auth/refresh` |
|
||||
| Per-user API key | `X-API-Key: m0sk_...` | Programmatic access scoped to a single dashboard user |
|
||||
| Legacy `ADMIN_API_KEY` | `X-API-Key: <env value>` | Back-compat for deployments that set the `ADMIN_API_KEY` env var |
|
||||
| `AUTH_DISABLED=true` | — | Local development only; bypasses auth entirely |
|
||||
|
||||
### Enable authentication
|
||||
The `/docs` OpenAPI explorer supports both auth modes. Click **Authorize** at the top of the page and paste either `Bearer <access_token>` (JWT) or your `X-API-Key` value. Protected endpoints return `401` until you authorize.
|
||||
|
||||
Add the key to your `.env` file:
|
||||
### Log in and use a JWT
|
||||
|
||||
Register the first admin (only works when no user exists yet), then log in:
|
||||
|
||||
```bash
|
||||
ADMIN_API_KEY=your-secret-api-key
|
||||
# First admin only — returns 403 after the first admin is registered
|
||||
curl -X POST http://localhost:8888/auth/register \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "Admin", "email": "admin@example.com", "password": "strong-password"}'
|
||||
```
|
||||
|
||||
Then include the header in every request:
|
||||
```bash
|
||||
curl -X POST http://localhost:8888/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email": "admin@example.com", "password": "your-password"}'
|
||||
```
|
||||
|
||||
Use the returned `access_token` as a bearer token:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/memories \
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-secret-api-key" \
|
||||
-H "Authorization: Bearer <access_token>" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I love pizza."}],
|
||||
"user_id": "alice"
|
||||
}'
|
||||
```
|
||||
|
||||
When the access token expires, exchange the refresh token at `POST /auth/refresh`.
|
||||
|
||||
### Create and use a per-user API key
|
||||
|
||||
Create a key from the dashboard **API Keys** page, or call `POST /api-keys` with a JWT. The full `m0sk_...` value is returned **once** at creation time — store it securely.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: m0sk_your_key_here" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I love pizza."}],
|
||||
"user_id": "alice"
|
||||
}'
|
||||
```
|
||||
|
||||
Per-user keys inherit the creating user's scope. List or revoke them via `GET /api-keys` and `DELETE /api-keys/{id}`.
|
||||
|
||||
### Legacy `ADMIN_API_KEY`
|
||||
|
||||
Set the `ADMIN_API_KEY` environment variable and send it as `X-API-Key`. The request is treated as admin-level and is not tied to a dashboard user. This mode is kept for back-compat with older self-hosted deployments — prefer JWT or per-user keys for new setups.
|
||||
|
||||
```bash
|
||||
ADMIN_API_KEY=your-long-admin-key
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The server logs a warning at startup when `ADMIN_API_KEY` is not set. Always set it in production.
|
||||
Setting `AUTH_DISABLED=true` makes every protected endpoint open — the server logs a warning at startup when it's enabled. The server also warns when `ADMIN_API_KEY` is shorter than 16 characters. Never enable `AUTH_DISABLED` in production, and always use a long `ADMIN_API_KEY` if you rely on the legacy fallback.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
@@ -136,7 +203,7 @@ curl -X POST http://localhost:8000/memories \
|
||||
### Create and search memories via HTTP
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/memories \
|
||||
curl -X POST http://localhost:8888/memories \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
@@ -151,7 +218,7 @@ curl -X POST http://localhost:8000/memories \
|
||||
</Info>
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/search \
|
||||
curl -X POST http://localhost:8888/search \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "vegetable",
|
||||
@@ -161,7 +228,7 @@ curl -X POST http://localhost:8000/search \
|
||||
|
||||
### Explore with OpenAPI docs
|
||||
|
||||
1. Navigate to `http://localhost:8000/docs`.
|
||||
1. Navigate to `http://localhost:8888/docs` (Compose) or `http://localhost:8000/docs` (raw Docker / uvicorn).
|
||||
2. Pick an endpoint (e.g., `POST /search`).
|
||||
3. Fill in parameters and click **Execute** to try requests in-browser.
|
||||
|
||||
@@ -175,9 +242,13 @@ curl -X POST http://localhost:8000/search \
|
||||
|
||||
The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
|
||||
### Memory operations
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/configure` | Set memory configuration |
|
||||
| `POST` | `/configure` | Set memory configuration. Rejects unbundled providers with a 400 |
|
||||
| `GET` | `/configure` | Get the current memory configuration |
|
||||
| `GET` | `/configure/providers` | List the LLM and embedder providers bundled in the container |
|
||||
| `POST` | `/memories` | Create memories |
|
||||
| `GET` | `/memories` | Get all memories (filter by `user_id`, `agent_id`, or `run_id`) |
|
||||
| `GET` | `/memories/{memory_id}` | Get a specific memory |
|
||||
@@ -188,6 +259,43 @@ The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
| `POST` | `/search` | Search memories |
|
||||
| `POST` | `/reset` | Reset all memories |
|
||||
|
||||
### Authentication
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/auth/setup-status` | Returns `{needsSetup: bool}`. Open, no auth required |
|
||||
| `POST` | `/auth/register` | Register the first admin. Registration closes after the first admin is created; additional accounts are provisioned by the existing admin. |
|
||||
| `POST` | `/auth/login` | Exchange email and password for access and refresh JWTs |
|
||||
| `POST` | `/auth/refresh` | Exchange a refresh token for a new access token |
|
||||
| `GET` | `/auth/me` | Get the current authenticated user (JWT required) |
|
||||
| `PATCH` | `/auth/me` | Update the caller's name or email. 409 if the new email is already in use |
|
||||
| `POST` | `/auth/change-password` | Change the caller's password. 401 if the current password is wrong; new password must be at least 8 characters |
|
||||
|
||||
### API keys
|
||||
|
||||
All `/api-keys` endpoints require a JWT.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api-keys` | List the caller's API keys |
|
||||
| `POST` | `/api-keys` | Create a new key; the full `m0sk_...` value is returned once |
|
||||
| `DELETE` | `/api-keys/{id}` | Revoke an API key |
|
||||
|
||||
### Request logs
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/requests?limit=N` | Recent API call log (JWT or admin key) |
|
||||
|
||||
### Entities
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/entities` | Distinct `user_id` / `agent_id` / `run_id` values with memory counts |
|
||||
| `DELETE` | `/entities/{entity_type}/{entity_id}` | Cascade-delete all memories for an entity; `entity_type` is `user`, `agent`, or `run` |
|
||||
|
||||
The `/auth/*`, `/api-keys`, `/requests`, and `/entities` routes are new to the self-hosted server and primarily back the dashboard, but you can call them directly from your own tooling.
|
||||
|
||||
---
|
||||
|
||||
## Verify the feature is working
|
||||
@@ -201,7 +309,7 @@ The OSS REST server exposes the following endpoints. None use the `/v1/` prefix.
|
||||
|
||||
## Best practices
|
||||
|
||||
1. **Enable authentication:** Set `ADMIN_API_KEY` to secure all endpoints, or use an API gateway for more advanced schemes.
|
||||
1. **Keep auth on:** Auth is enabled by default. Never set `AUTH_DISABLED=true` in production. If you rely on `ADMIN_API_KEY`, use a long value (16+ chars) or prefer per-user API keys.
|
||||
2. **Use HTTPS:** Terminate TLS at your load balancer or reverse proxy.
|
||||
3. **Monitor uptime:** Track request rates, latency, and error codes per endpoint.
|
||||
4. **Version configs:** Keep environment files and Docker Compose definitions in source control.
|
||||
|
||||
@@ -15,12 +15,15 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
- **Extendable codebase**: Fork the repo, add providers, and ship custom automations.
|
||||
|
||||
<Info>
|
||||
Begin with the <Link href="/open-source/python-quickstart">Python quickstart</Link> (or the Node.js variant) to clone the repo, configure dependencies, and validate memory reads/writes locally.
|
||||
Two ways to run Mem0 OSS: as a **library** inside your app (Python or Node), or as a **self-hosted server** with a dashboard, per-user API keys, and a request audit log.
|
||||
</Info>
|
||||
|
||||
## Choose your path
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Self-hosted setup" icon="rocket-launch" href="/open-source/setup">
|
||||
Run `make bootstrap` to launch the server + dashboard, create an admin, and issue your first API key.
|
||||
</Card>
|
||||
<Card title="Python Quickstart" icon="python" href="/open-source/python-quickstart">
|
||||
Bootstrap CLI and verify add/search loop.
|
||||
</Card>
|
||||
@@ -41,15 +44,6 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Deploy with Docker Compose" icon="server" href="/open-source/features/rest-api">
|
||||
Reference deployment with REST endpoints.
|
||||
</Card>
|
||||
<Card title="Use the REST API" icon="code" href="/open-source/features/rest-api">
|
||||
Async add/search flows and automation.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Need a managed alternative? Compare hosting models in the <Link href="/platform/platform-vs-oss">Platform vs OSS guide</Link> or switch tabs to the Platform documentation.
|
||||
</Tip>
|
||||
@@ -70,19 +64,27 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
## Default components
|
||||
|
||||
<Note>
|
||||
Mem0 OSS works out of the box with sensible defaults:
|
||||
**Library defaults** (when you `import` Mem0 and call `Memory()` directly):
|
||||
- LLM: OpenAI `gpt-5-mini` (via `OPENAI_API_KEY`)
|
||||
- Embeddings: OpenAI `text-embedding-3-small`
|
||||
- Vector store: Local Qdrant instance storing data at `/tmp/qdrant`
|
||||
- History store: SQLite database at `~/.mem0/history.db`
|
||||
- Reranker: Disabled until you configure a provider
|
||||
- Vector store: Local Qdrant at `/tmp/qdrant`
|
||||
- History store: SQLite at `~/.mem0/history.db`
|
||||
- Reranker: Disabled until configured
|
||||
|
||||
Override any component with <Link href="/open-source/configuration">`Memory.from_config`</Link>.
|
||||
</Note>
|
||||
|
||||
## Keep going
|
||||
<Note>
|
||||
**Self-hosted server defaults** (the `server/` Docker Compose stack):
|
||||
- LLM: OpenAI `gpt-4.1-nano-2025-04-14` (override with `MEM0_DEFAULT_LLM_MODEL`)
|
||||
- Embeddings: OpenAI `text-embedding-3-small` (override with `MEM0_DEFAULT_EMBEDDER_MODEL`)
|
||||
- Vector store: Postgres + pgvector
|
||||
- Bundled providers: `openai`, `anthropic`, `gemini` — switch from the Configuration page
|
||||
|
||||
{/* DEBUG: verify CTA targets */}
|
||||
See <Link href="/open-source/setup#supported-providers">Self-Hosted Setup</Link> for the full provider list and how to extend it.
|
||||
</Note>
|
||||
|
||||
## Keep going
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
@@ -98,7 +100,3 @@ Mem0 Open Source delivers the same adaptive memory engine as the platform, but p
|
||||
href="/open-source/python-quickstart"
|
||||
/>
|
||||
</CardGroup>
|
||||
|
||||
<Tip>
|
||||
Need a managed alternative? Compare hosting models in the <Link href="/platform/platform-vs-oss">Platform vs OSS guide</Link> or switch tabs to the Platform documentation.
|
||||
</Tip>
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
---
|
||||
title: "Self-Hosted Setup"
|
||||
description: "Stand up the Mem0 REST server and dashboard in a few minutes — admin account, API keys, and a live audit log included."
|
||||
icon: "rocket-launch"
|
||||
---
|
||||
|
||||
The self-hosted bundle ships the REST API and a web dashboard together. Configure your LLM provider and secrets in a `.env` file, start the containers, then choose how to create your admin account: through the browser-based setup wizard, or from the command line.
|
||||
|
||||
<Info>
|
||||
**Use this page when…**
|
||||
- You want a self-hosted Mem0 with a dashboard, not just the Python or Node library.
|
||||
- You need per-user API keys and a request audit log for your team.
|
||||
- You're upgrading from a pre-1.x server that relied on `ADMIN_API_KEY` or open endpoints.
|
||||
</Info>
|
||||
|
||||
<Warning>
|
||||
**Upgrading from 1.x?** Auth is now on by default. Deployments that ran with an empty `ADMIN_API_KEY` will return `401` on every protected endpoint until you either set `ADMIN_API_KEY`, register an admin through the wizard, or set `AUTH_DISABLED=true` for local development. See [Upgrade notes](#upgrade-notes) below.
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker and Docker Compose (the reference path).
|
||||
- An `OPENAI_API_KEY` (or equivalent — the server reads the same component config as the library).
|
||||
- A free port `8888` for the API and `3000` for the dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Configure the environment
|
||||
|
||||
Copy `server/.env.example` to `server/.env` and fill in the required values. The server refuses to start if `JWT_SECRET` is unset once auth is enabled.
|
||||
|
||||
| Variable | Required | Purpose |
|
||||
|---|---|---|
|
||||
| `OPENAI_API_KEY` | Yes | Default LLM and embedder provider. |
|
||||
| `JWT_SECRET` | Yes | Signs access and refresh tokens. Use a long random value. A missing secret causes auth endpoints to return `500`. |
|
||||
| `ADMIN_API_KEY` | Optional | Legacy shared admin key. Kept for back-compat; prefer per-user keys for new setups. |
|
||||
| `AUTH_DISABLED` | Optional | `true` turns off auth for local development only. Never enable in production. |
|
||||
| `DASHBOARD_URL` | Optional | Origin the API accepts for CORS. Defaults to `http://localhost:3000`. Set this when you front the dashboard on a custom domain. |
|
||||
| `POSTGRES_*` | Optional | Override the bundled Postgres / pgvector connection. |
|
||||
|
||||
<Tip>
|
||||
Generate a `JWT_SECRET` with `openssl rand -base64 48` or `python -c "import secrets; print(secrets.token_urlsafe(48))"`.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Start the stack
|
||||
|
||||
Pick the path that fits your workflow.
|
||||
|
||||
### Browser-first (setup wizard)
|
||||
|
||||
```bash
|
||||
cd server
|
||||
make up
|
||||
```
|
||||
|
||||
This starts the containers and runs database migrations. The REST API listens on `http://localhost:8888` and the dashboard on `http://localhost:3000`.
|
||||
|
||||
Open `http://localhost:3000` — since no admin account exists yet, the dashboard redirects to the one-time setup wizard at `/setup`. See [Run the setup wizard](#run-the-setup-wizard) below.
|
||||
|
||||
### Agent-first (command line)
|
||||
|
||||
First, set `OPENAI_API_KEY` (or `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY`) in `server/.env`. `make bootstrap` does not prompt for it, and the runtime test will fail without a valid provider key.
|
||||
|
||||
```bash
|
||||
cd server
|
||||
make bootstrap
|
||||
```
|
||||
|
||||
`make bootstrap` starts the same containers, then automatically creates the admin account and generates the first API key via the CLI. The admin credentials and API key are printed to your terminal — no browser required.
|
||||
|
||||
You can override the generated credentials:
|
||||
|
||||
```bash
|
||||
make bootstrap EMAIL=admin@company.com PASSWORD='strong-password' NAME='Admin'
|
||||
```
|
||||
|
||||
Because `make bootstrap` already creates the admin, the setup wizard is skipped. Opening `http://localhost:3000` takes you straight to the login page.
|
||||
|
||||
<Tip>
|
||||
For machine-readable output (useful in CI), run `OUTPUT=json make seed` after `make up`.
|
||||
</Tip>
|
||||
|
||||
---
|
||||
|
||||
## Run the setup wizard
|
||||
|
||||
<Info>
|
||||
This section applies to the **browser-first** path (`make up`). If you used `make bootstrap`, the admin and API key were already created — skip ahead to [What the dashboard gives you](#what-the-dashboard-gives-you).
|
||||
</Info>
|
||||
|
||||
On a fresh install the dashboard redirects to `/setup`. Each step submits on Enter.
|
||||
|
||||
**1. Create the admin account.** Name, email, password. This account becomes the first admin. Registration closes after the first admin is created; additional accounts are provisioned by the existing admin.
|
||||
|
||||
**2. Review the effective config.** Read-only display of the LLM and embedder the server is running with, sourced from your environment. If anything is wrong here, stop the stack, fix the `.env`, and restart — the dashboard intentionally does not let you change provider secrets at runtime.
|
||||
|
||||
**3. Generate your first API key.** The full `m0sk_...` value is shown **once**. Copy it immediately — the server only stores the prefix and a bcrypt hash.
|
||||
|
||||
**4. Tell us your use case.** Pick a preset or describe your use case in a few words. Mem0 generates custom instructions that tell the memory system what to prioritize. You can edit the instructions before saving, or skip this step entirely.
|
||||
|
||||
**5. Test the key.** A ready-to-paste `curl` exercises `POST /memories` against your new key. Click "Run Test" to fire it from the browser. Success lands you in the dashboard at `/dashboard/requests`, where you'll see the test call in the live audit log.
|
||||
|
||||
---
|
||||
|
||||
## What the dashboard gives you
|
||||
|
||||
| Page | What it does |
|
||||
|---|---|
|
||||
| **Requests** | Default landing page. Live audit log of every API call, with status, latency, and auth mode. |
|
||||
| **Memories** | Browse and search the memories your server has stored. |
|
||||
| **Entities** | Distinct `user_id` / `agent_id` / `run_id` values with memory counts and cascade-delete. |
|
||||
| **API Keys** | Issue per-user keys, label them, and revoke. |
|
||||
| **Configuration** | Runtime override for LLM and embedder. Changes persist to the app database and reapply on restart, layered over the values from your `.env`. |
|
||||
| **Settings** | Account and session controls. |
|
||||
|
||||
For the underlying endpoints (including `/auth/*`, `/api-keys`, `/requests`, `/entities`), see the [REST API reference](/open-source/features/rest-api).
|
||||
|
||||
---
|
||||
|
||||
## Supported providers
|
||||
|
||||
The shipped container bundles the Python packages for:
|
||||
|
||||
- **LLMs** — `openai`, `anthropic`, `gemini`
|
||||
- **Embedders** — `openai`, `gemini`
|
||||
|
||||
The Configuration page and `POST /configure` only accept providers from these lists. Anything else returns a 400 up front instead of failing at the first memory write.
|
||||
|
||||
**To add another provider**, for example to run embeddings locally with `sentence-transformers`:
|
||||
|
||||
1. Add the package to `server/requirements.txt` (e.g. `sentence-transformers>=2.0`).
|
||||
2. Extend `BUNDLED_LLM_PROVIDERS` or `BUNDLED_EMBEDDER_PROVIDERS` in `server/main.py`.
|
||||
3. Rebuild the image (`make up` or `docker compose build`).
|
||||
|
||||
Heavy providers (`sentence-transformers` pulls in PyTorch, ~2 GB) are intentionally kept out of the default image.
|
||||
|
||||
---
|
||||
|
||||
## Upgrade notes
|
||||
|
||||
### Upgrading from a pre-auth build
|
||||
|
||||
Previous self-hosted builds allowed open access when `ADMIN_API_KEY` was unset. This build enables auth by default. After pulling the new image, pick **one**:
|
||||
|
||||
1. **Fastest, zero client changes** — set `ADMIN_API_KEY` to a long random value (16+ characters). Existing clients that send `X-API-Key: <your-key>` keep working unchanged.
|
||||
2. **Recommended for teams** — visit `http://<host>:3000`, run the setup wizard, and switch clients to per-user API keys. You get the audit log and revocation for free.
|
||||
3. **Local development only** — set `AUTH_DISABLED=true`. The server logs a warning on every boot. Never use this in production.
|
||||
|
||||
The server prints an unmissable startup banner when it detects the "upgraded but not configured" state so you know exactly which option to pick.
|
||||
|
||||
### Other changes in this release
|
||||
|
||||
- Dashboard ships as a second container in the reference Compose stack, wired to the API over the internal Docker network.
|
||||
- New tables: `users`, `api_keys`, `request_logs`. Alembic handles the migration automatically on first boot.
|
||||
|
||||
If `alembic upgrade head` fails on first boot, see the [Troubleshooting](#troubleshooting) section below.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Port 3000 or 8888 is already in use">
|
||||
Find the owning process on either port:
|
||||
```bash
|
||||
lsof -iTCP:3000 -sTCP:LISTEN
|
||||
lsof -iTCP:8888 -sTCP:LISTEN
|
||||
```
|
||||
Kill it (`kill <PID>`) or change the host port in `server/docker-compose.yaml`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="JWT_SECRET is required">
|
||||
The server refuses to start without one. Generate a secret and add it to `server/.env`:
|
||||
```bash
|
||||
echo "JWT_SECRET=$(openssl rand -base64 48)" >> server/.env
|
||||
```
|
||||
`AUTH_DISABLED=true` is valid for local dev only, never production.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title=".env changes aren't applied after editing">
|
||||
`docker compose restart` does not re-read `env_file`. To pick up changes:
|
||||
```bash
|
||||
cd server && docker compose up -d --force-recreate mem0
|
||||
# or
|
||||
cd server && make up
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Provider returns 401 (bad API key)">
|
||||
Provider credential errors surface as `502 Upstream provider error.`. Check `docker compose logs mem0` for the full trace, then fix the key on the Configuration page and hit **Save**.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Alembic migrations fail on startup">
|
||||
Inspect the logs:
|
||||
```bash
|
||||
docker compose logs mem0 | grep -i alembic
|
||||
```
|
||||
If the database is unrecoverable, reset the volume (**this destroys all memories and users**):
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="REST API reference" icon="code" href="/open-source/features/rest-api">
|
||||
Endpoint tables, auth modes, and example requests.
|
||||
</Card>
|
||||
<Card title="Configure components" icon="sliders" href="/open-source/configuration">
|
||||
Swap LLMs, embedders, vector stores, and rerankers.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Reference in New Issue
Block a user