server/README.md
Mem0 ships a self-hosted FastAPI server plus a local dashboard. It is secure by default, supports dashboard login and API keys, and exposes OpenAPI docs at /docs.
Upgrading? The Postgres image changed from the archived
ankane/pgvector:v0.5.1to the officialpgvector/pgvector:pg17, andPOSTGRES_PASSWORDis now a required env var. If you have an existing install, see Migrating from ankane/pgvector to pgvector/pgvector before runningdocker compose up.
Copy the example env file and set a Postgres password (required):
cd server
cp .env.example .env
# Edit .env — at minimum set POSTGRES_PASSWORD and OPENAI_API_KEY
Run one command; the terminal prints the admin email, password, and first API key.
cd server
make bootstrap
This starts the stack, waits for the API and dashboard to be ready, creates the first admin, and generates the first API key.
The generated credentials print once in the
=== Ready ===block. Save the password and API key before closing the terminal — the API key cannot be recovered afterwards.
make bootstrapskips the setup wizard, so the use-case → custom-instructions step doesn't run. To add custom instructions afterwards,POST /configurewith{"custom_instructions": "..."}, or run the Browser-first flow on a fresh install.
You can override the generated credentials:
cd server
make bootstrap [email protected] PASSWORD='strong-password' NAME='Admin'
For machine-readable output:
cd server
OUTPUT=json make seed
Teardown:
# Stop the stack
cd server && make down
# Wipe all data (including the Postgres volume)
cd server && make clean
Start the stack and finish setup by walking through the wizard in your browser.
cd server
make up
Then open http://localhost:3000 and complete the setup wizard.
X-API-Key.AUTH_DISABLED=true exists for local development only and should not be used in production.Reset an admin password from the host while the stack is running:
cd server
make reset-admin-password [email protected] PASSWORD='new-strong-password'
This is the supported recovery path. Anyone with shell access to the host already has full access to the database and secrets, so this command does not expand the attack surface.
The request_logs table is append-only and grows with traffic (~864k rows/day at 10 req/s). Prune it periodically:
cd server
make prune-logs # defaults to 30 days
make prune-logs REQUEST_LOG_RETENTION_DAYS=7 # shorter window
Wire the command into cron or a systemd timer in production. The created_at column uses a BRIN index, so range deletes stay cheap even on large tables.
http://localhost:3000http://localhost:8888http://localhost:8888/docsOnce logged in, the dashboard exposes:
user_id, agent_id, and run_id that owns memories, with counts. Delete an entity to cascade-delete its memories..env.Enabled by default, matching the Mem0 OSS library. Sends at most two events per install to the same anonymous PostHog project the library uses:
admin_registered — fired when the first admin is created (wizard or direct API call). Properties: email domain, server version, install UUID.onboarding_completed — fired when the setup wizard reaches its final success state. Carries the same properties plus the freeform use_case the operator entered. API-only bootstraps never emit this event.Set MEM0_TELEMETRY=false to opt out.
The dashboard sets the following response headers on every path (see server/dashboard/next.config.mjs):
X-Frame-Options: DENYContent-Security-Policy: frame-ancestors 'none'X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originTogether these prevent iframe embedding, sniffing of mislabelled MIME types, and cross-origin referrer leaks. Harden further behind your own reverse proxy if needed.
ankane/pgvector to pgvector/pgvectorThe ankane/pgvector Docker image is archived and no longer maintained. This release
replaces it with the official pgvector/pgvector:pg17 image (PostgreSQL 17, pgvector 0.8.0).
What changed:
| Before | After | |
|---|---|---|
| Docker image | ankane/pgvector:v0.5.1 | pgvector/pgvector:pg17 |
| PostgreSQL version | 15 | 17 |
| pgvector version | 0.5.1 | 0.8.0 |
| Credentials | Hardcoded postgres/postgres | Driven by POSTGRES_USER / POSTGRES_PASSWORD env vars |
No migration needed. Copy .env.example to .env, set POSTGRES_PASSWORD, and run:
cd server
make up
PostgreSQL 17 cannot read data files written by PostgreSQL 15 directly. You must export your data first, then import it into the new container.
1. Export your data from the old container
With the old stack still running:
cd server
# Dump all databases (mem0 memories + mem0_app auth/config data)
docker compose exec -T postgres pg_dumpall -U postgres > mem0_backup.sql
Verify the dump file is non-empty:
ls -lh mem0_backup.sql
2. Stop the old stack and remove the old volume
# Stop containers
docker compose down
# Remove the old Postgres data volume
docker compose down -v
Warning:
docker compose down -vdeletes thepostgres_dbvolume permanently. Only run this after you have verified your backup.
3. Update your .env
The Postgres credentials are no longer hardcoded in docker-compose.yaml.
Add them to your .env file (or verify they match your old setup):
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<your-password> # required — compose will refuse to start without it
POSTGRES_COLLECTION_NAME=memories
If you previously relied on the hardcoded defaults (postgres/postgres), set
POSTGRES_PASSWORD=postgres to keep the same credentials.
4. Start only Postgres
Start only the Postgres container first — do not start the mem0 API yet.
The API runs alembic upgrade head on startup, which creates empty tables that
would conflict with the restore.
docker compose up -d postgres
Wait for the Postgres healthcheck to pass:
docker compose exec -T postgres pg_isready -q && echo "ready" || echo "not ready"
5. Restore your data
docker compose exec -T postgres psql -U postgres < mem0_backup.sql
You may see notices like role "postgres" already exists — these are harmless.
Important: You must restore before starting the mem0 API container. The API runs database migrations on startup which create empty tables — restoring after that would fail with duplicate-key errors and lose your API keys and settings.
6. Start the API
Now start the mem0 API container. Alembic will detect the existing tables and only apply any new migrations:
docker compose up -d mem0
7. Verify
# Check the API is healthy
make health
# Confirm your memories are present
curl -s http://localhost:8888/memories?user_id=<your-user-id> -H "X-API-Key: <your-api-key>"
If you need to revert, restore the old image tag in docker-compose.yaml:
postgres:
image: ankane/pgvector:v0.5.1
Then docker compose down -v, docker compose up -d --build, and restore from
mem0_backup.sql into the old container the same way.
Additional product and API documentation lives at docs.mem0.ai.