Run the standalone service
Introduction
Section titled “Introduction”apps/brain-api is Brain as a service: NestJS and PostgreSQL, the REST API, the MCP endpoint at /mcp, Google sign-in, and the built web app (apps/brain-web) served from the same port. It is the example host for embedding Brain.
Prerequisites
Section titled “Prerequisites”- PostgreSQL with the pgvector extension available. On boot the service runs
CREATE EXTENSION IF NOT EXISTS vector, creates thepilotoo_brainschema with its tables, and creates the sign-in tables beside them. Both steps are idempotent and locked, so several instances may start together. - A Google OAuth client of type Web application, with
https://<your host>/auth/google/callbackas an authorised redirect URI. - Optional: a Bedrock API key (or another provider’s key) for a chat model, and an embeddings provider.
Run it with Docker
Section titled “Run it with Docker”Build from the repository root:
docker build -f apps/brain-api/Dockerfile -t pilotoo-brain .docker run --env-file brain.env -p 4320:4320 pilotoo-brainThe image runs as an unprivileged user and listens on PORT (4320). Put it behind a proxy that terminates TLS; BRAIN_PUBLIC_URL must be https outside localhost.
DATABASE_URL=postgres://user:password@db:5432/pilotoo_brainBRAIN_PUBLIC_URL=https://brain.example.comBRAIN_SESSION_SECRET=<32 or more random characters>GOOGLE_CLIENT_ID=<web client id>GOOGLE_CLIENT_SECRET=<web client secret>BRAIN_ALLOWED_EMAILS=ada@example.com,grace@example.comBRAIN_ADMIN_EMAILS=ada@example.comBoot fails naming every required setting that is missing or malformed, never a value.
Settings
Section titled “Settings”| Variable | Default | Meaning |
|---|---|---|
DATABASE_URL |
required | PostgreSQL with pgvector. |
BRAIN_PUBLIC_URL |
required | Public origin people reach the service at. Sign-in derives from it; https outside localhost. |
BRAIN_SESSION_SECRET |
required | At least 32 characters. Signs the session and login cookies. |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
required | The Google OAuth client. |
PORT |
4320 |
Listening port. |
BRAIN_ALLOWED_EMAILS |
nobody | Comma-separated emails that may sign in. * admits every verified Google account. |
BRAIN_ADMIN_EMAILS |
none | Comma-separated emails that are workspace admins. |
BRAIN_MODEL |
off | Chat model as provider:modelId, for page compilation, answers and label suggestions. Unset: those features are off. |
ANTHROPIC_BEDROCK_REGION |
none | Region for the anthropic-bedrock provider. |
AWS_BEARER_TOKEN_BEDROCK |
none | Bedrock API key. Also the default key for Titan embeddings. |
OPENAI_API_KEY, OPENAI_BASE_URL, ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, AI_DEEPSEEK_API_KEY, AI_DEEPSEEK_BASE_URL |
none | Keys and base URLs of the other model providers. |
BRAIN_EMBEDDINGS_PROVIDER |
off | bedrock-titan or openai-compatible. Unset: search is full-text only. |
BRAIN_EMBEDDINGS_REGION |
none | Required for bedrock-titan. Independent of the chat model’s region. |
BRAIN_EMBEDDINGS_API_KEY |
AWS_BEARER_TOKEN_BEDROCK for bedrock-titan |
Embeddings key. Required for openai-compatible. |
BRAIN_EMBEDDINGS_MODEL |
amazon.titan-embed-text-v2:0 for bedrock-titan |
Required for openai-compatible. |
BRAIN_EMBEDDINGS_DIMENSIONS |
1024 for bedrock-titan |
Vector width, a whole number from 1 to 16000. |
BRAIN_EMBEDDINGS_BASE_URL |
OpenAI | openai-compatible only: the server’s base URL, such as https://api.openai.com/v1. |
BRAIN_TENANT |
brain |
Tenant name recorded for signed-in people. |
BRAIN_WEB_DIST |
/app/web in the image |
Directory of the built web app to serve. |
BRAIN_OIDC_ISSUER |
Override of the OIDC issuer. | |
BRAIN_ENV_FILE |
none | A file of settings loaded at start, for local runs. |
When BRAIN_EMBEDDINGS_PROVIDER is unset but both an embeddings key and model are set, openai-compatible is used.
Sign in
Section titled “Sign in”People sign in with Google at /auth/google/start. The session is a signed cookie; a person not in BRAIN_ALLOWED_EMAILS is sent back to /?error=not_allowed. Signing in creates the person’s personal memory. Agents do not use the cookie; they use pb_ tokens on /mcp, see Use it from an agent.
GET /health answers {"status":"ok"} without a session, for a proxy or orchestrator health check.
Next steps
Section titled “Next steps”- Use it from an agent to connect an MCP client.
- Shared sign-in for how the login is built.