Guides / Brain

Securing a shared brain

What to check before you open the brain to other machines, including client registration.

By default your brain only talks to programs on the same computer. The moment you start it with nexusbrain serve --http and let other machines reach it, anyone who can reach the address can try to use it, so the credentials, network settings and client registration rules below start to matter.

This guide explains the two ways the brain serves agents, how to open the HTTP server safely, how access tokens and OAuth clients work, what dynamic client registration is and when to turn it on, and how to remove access again. It ends with a checklist for a shared deployment.

Time
20 minutes
For
Anyone running `nexusbrain serve --http` for more than one machine, person or cloud service

Before you start

  • The nexusbrain CLI is installed and a brain is set up. The nexusbrain auth commands need a brain to write to; without one they stop with "No Nexus Brain config found. Run nexusbrain init first, or set DATABASE_URL / NEXUS_BRAIN_DATABASE_URL."
  • You run the nexusbrain auth commands on the brain host, where the database lives.
  • For anything reachable from the internet: an HTTPS address in front of the brain, such as a reverse proxy or a tunnel. The brain server itself listens on plain HTTP.

01Local serving and HTTP serving

MCP is the protocol agents use to call the brain's tools. The brain can speak it in two ways, and they have very different exposure.

  1. Start the HTTP server with its defaults.

    The default port is 3131. Use --port to pick another one. Access tokens last 3600 seconds unless you pass --token-ttl with a number of seconds.

    nexusbrain serve --http

    You should seeA startup box listing Port 3131, Bind 127.0.0.1, the Issuer, the number of Clients, "DCR: disabled", and the Admin, MCP and Health addresses on http://localhost:3131.

  2. Check that the server answers.

    curl http://localhost:3131/health

    You should seeA small JSON reply with "status":"ok", the version and the engine name.

CommandHow agents connectWho can reach it
nexusbrain serveOver stdio. The agent starts the brain as a child process and talks to it through its input and output.Only the program that started it. Nothing listens on the network.
nexusbrain serve --httpOver HTTP at /mcp, with OAuth 2.1 and bearer tokens.Whatever can reach the interface it binds to. The default is 127.0.0.1, so only this computer.
Tip

If only agents on your own computer need the brain, nexusbrain serve over stdio is the smallest exposure. You do not need anything else in this guide.

02Open the HTTP server to other machines

Three settings decide who can reach the server and whether OAuth clients trust it: the interface it binds to, the public address it announces, and how it treats a proxy in front of it.

  1. Put an HTTPS address in front of the brain.

    Use a reverse proxy or a tunnel that ends HTTPS and forwards to the brain's port. Tokens and client secrets travel in request headers, so plain HTTP across a network exposes them. nexusbrain connect warns "http:// sends your bearer token unencrypted. Use https:// unless this is localhost." for the same reason.

    You should seeYour HTTPS address forwards to port 3131 (or the port you chose) on the brain host.

  2. Start the server bound for remote access, with its public address.

    Replace https://brain.example.com with your own HTTPS address. Always pass --bind together with --public-url. If you set only --public-url, the server stays on 127.0.0.1 and warns that remote clients reaching the public URL will be refused.

    nexusbrain serve --http --bind 0.0.0.0 --public-url https://brain.example.com

    You should seeThe startup box shows Bind 0.0.0.0 and your address as the Issuer.

  3. Tell the server about your proxy, if you use one.

    Only set this when the brain is reachable through the proxy alone and the proxy replaces any X-Forwarded-For header the client sent. Otherwise a client can fake its address and slip past the per-address rate limit.

    NEXUS_BRAIN_HTTP_TRUST_PROXY=1 nexusbrain serve --http --bind 0.0.0.0 --public-url https://brain.example.com

    You should seeThe server starts as before. Rate limits now count the real client address.

  4. Allow browser origins only if a browser-based client needs them.

    With --bind 0.0.0.0 and no allowlist the server prints a warning that OAuth endpoints will reject all cross-origin requests. That is the safe default. Add origins only for web apps you trust.

    NEXUS_BRAIN_HTTP_CORS_ORIGIN=https://app.example.com nexusbrain serve --http --bind 0.0.0.0 --public-url https://brain.example.com

    You should seeThe CORS warning no longer appears.

SettingWhat it does
--bind <host>Network interface to listen on. Default 127.0.0.1 (this computer only). 0.0.0.0 accepts every interface; you can also give one interface IP.
--public-url <url>The public address clients use, for example https://brain.example.com. It becomes the OAuth issuer, so it must match the address clients actually open. Without it the issuer is http://localhost:<port>.
--port <n>Port to listen on. Default 3131.
NEXUS_BRAIN_HTTP_TRUST_PROXYHow many proxy hops to trust for the real client address. Unset means loopback only. 1 or true trusts one hop, 0 or false trusts none, another number trusts that many hops.
NEXUS_BRAIN_HTTP_CORS_ORIGINComma separated list of web origins allowed to call the OAuth endpoints and /mcp from a browser. Unset means every cross-origin browser request is refused. Requests without an Origin header are not affected.
NEXUS_BRAIN_OAUTH_TOKEN_RATE_LIMIT_WINDOW_MS and NEXUS_BRAIN_OAUTH_TOKEN_RATE_LIMIT_MAXRate limit on the token and revoke endpoints. Defaults: 50 requests per 15 minutes.
Warning

Do not bind to 0.0.0.0 on a laptop on a shared network unless you mean to. Before v0.34.1 that was the default, and it published the brain to everyone on the same network.

03Give each agent its own credential

There are two kinds of credential. A bearer token (also called an API key) is one long secret with full access; it suits your own tools on your own machines. An OAuth client has a client ID and client secret, gets limited scopes and trades them for short-lived access tokens; it is the right choice for anything exposed to a third-party cloud service.

Scopes decide what an OAuth client may do. admin includes sources_admin, users_admin, write and read. write includes read. agent is separate, and even admin does not include it.

  1. Create a bearer token for a trusted tool.

    Each token needs a unique name, which you later use to revoke it. --takes-holders world,alice sets which takes holders the token may see; the default is world only, which keeps private takes hidden.

    nexusbrain auth create "claude-desktop"

    You should seeThe token, starting with nexusbrain_, a reminder to save it because it will not be shown again, and the command to revoke it.

  2. Register an OAuth client with only the scopes it needs.

    nexusbrain auth register-client "reporting-bot" --grant-types client_credentials --scopes read

    You should seeAn "OAuth client registered" block with the Client ID (starting nexusbrain_cl_), the Client Secret, grant types, scopes, token auth method, write source and federated reads, then a reminder to save the client secret because it will not be shown again.

  3. Narrow the client further if it writes or runs agents.

    Use the options in the table below. For example, --bound-slug-prefixes team/alice/ keeps every page write from that client inside team/alice/. Each prefix must end with / or /*.

    You should seeThe registration block also lists Bound tools, Bound source, Bound brain, Bound slug prefixes, Max concurrency and Daily budget USD.

  4. Change a client's source scope later without re-registering it.

    Only the flags you pass change: --source, --federated-read, or --bound-slug-prefixes (use none to clear the fence).

    nexusbrain auth rescope-client nexusbrain_cl_xxx --federated-read default,notes

    You should see"OAuth client rescoped" with the new values, and "Takes effect on the client's next request (existing tokens included)."

  • --grant-types: client_credentials (default) for machine clients, or authorization_code, which is set automatically together with refresh_token when you pass --redirect-uri.
  • --redirect-uri <https://...>: repeatable. Required for the authorization_code grant.
  • --token-endpoint-auth-method: client_secret_post (default), client_secret_basic, or none for a public client that uses PKCE and gets no secret.
  • --source <id> and --federated-read <id1,id2>: which source the client writes to (default default) and which sources it can read (default: its write source).
  • --bound-tools, --bound-source, --bound-brain, --bound-slug-prefixes, --bound-max-concurrent, --budget-usd-per-day: limits on what the client may touch and spend.
ScopeAllows
readReading and searching the brain. The default for nexusbrain auth register-client.
writeWriting pages, plus everything read allows.
adminEverything except agent. Needed for admin-level tools such as submitting jobs.
sources_adminManaging sources.
users_adminManaging user accounts.
agentSubmitting subagent runs. Give it with the --bound-* limits below.
Warning

A bearer token from nexusbrain auth create is long-lived and has full access. Treat it like a password, never paste it into a shared document or a log, and prefer an OAuth client with narrow scopes for any cloud service.

04Decide about dynamic client registration

Dynamic client registration (DCR) lets an MCP client create its own OAuth client by calling the server's /register endpoint, instead of you running nexusbrain auth register-client for it. Some MCP apps expect it so they can connect with only a URL.

The catch: /register needs no login. When DCR is on, any network caller that can reach the server can register a client. It is off by default, and with it off the /register endpoint does not exist.

  1. Turn DCR on only while a client needs to register itself.

    nexusbrain serve --http --bind 0.0.0.0 --public-url https://brain.example.com --enable-dcr

    You should seeThe startup box shows "DCR: enabled" and stderr prints "SECURITY WARNING: Dynamic Client Registration (--enable-dcr) is ON. Any network caller can self-register an OAuth client."

  2. Connect the client, then restart the server without the flag.

    Clients that already registered keep working after DCR is turned off, because turning it off only removes the /register endpoint. Self-registered clients start on the default source; widen them with nexusbrain auth rescope-client if needed.

    You should seeThe startup box shows "DCR: disabled" again.

FlagEffect
(none)DCR off. Clients are created only with nexusbrain auth register-client or the admin dashboard.
--enable-dcrDCR on. Self-registered clients get the authorization_code grant, so a person must approve them on the consent screen. A request for client_credentials is refused.
--enable-dcr-insecureAlso lets self-registered clients use client_credentials, which skips the consent screen entirely. Implies --enable-dcr.
Warning

Never use --enable-dcr-insecure on a server reachable from the internet. With it on, the server prints "SECURITY WARNING: --enable-dcr-insecure is ON" and any caller can register a client that gets tokens without anyone approving it. Only use it on a trusted network.

05Protect the admin dashboard

The HTTP server also serves an admin dashboard at /admin. You sign in with an admin bootstrap token. The dashboard's Agents page lists every OAuth client and API key with its scopes, status and request counts, and lets you create clients (+ OAuth Client), create keys (+ API Key) and revoke them (Revoke Agent).

  1. Set a fixed admin token for a long-running deployment.

    Without this variable a new token is generated on every start. It is printed only when the terminal is interactive, so it does not end up in container logs. --print-admin-token forces it to print anyway; --suppress-bootstrap-token always hides it.

    The value must be at least 32 characters of letters, digits, _ or -, or the server refuses to start.

    NEXUS_BRAIN_ADMIN_BOOTSTRAP_TOKEN=<at-least-32-random-characters> nexusbrain serve --http --bind 0.0.0.0 --public-url https://brain.example.com

    You should seeThe startup box reads "Admin Token: from $NEXUS_BRAIN_ADMIN_BOOTSTRAP_TOKEN" instead of printing the value.

  2. Sign out every admin session if a token may have leaked.

    Click Sign out everywhere in the dashboard. It revokes every active admin session in every browser. Then restart the server with a new NEXUS_BRAIN_ADMIN_BOOTSTRAP_TOKEN.

    You should seeEvery admin session is signed out, including yours, so each browser has to sign in again.

Warning

Leave --log-full-params off on shared servers. It stores raw request payloads in the request log and the live dashboard feed, and prints a warning to say so. By default only a summary without values is kept.

06Remove access

  1. List bearer tokens and their status.

    nexusbrain auth list

    You should seeA table with Name, Created, Last Used and Status (active or REVOKED).

  2. Revoke a bearer token by name.

    nexusbrain auth revoke "claude-desktop"

    You should seeToken "claude-desktop" revoked.

  3. Find the client ID of an OAuth client.

    There is no CLI command that lists OAuth clients. Use the Agents page in the admin dashboard, or the Client ID you saved when you registered it.

    You should seeYou have the client ID, which starts with nexusbrain_cl_.

  4. Revoke the OAuth client.

    This deletes the client for good, together with all its access tokens and authorization codes. To give that agent access again, register a new client.

    nexusbrain auth revoke-client nexusbrain_cl_xxx

    You should seeOAuth client revoked: "reporting-bot" (nexusbrain_cl_xxx), then "Tokens and authorization codes purged via cascade."

07Checklist for a shared deployment

  • Clients reach the brain only through HTTPS, and --public-url is exactly that HTTPS address.
  • --bind is set on purpose, not left to the default when you also set --public-url.
  • NEXUS_BRAIN_HTTP_TRUST_PROXY is set only if the brain sits behind a proxy that rewrites X-Forwarded-For.
  • NEXUS_BRAIN_HTTP_CORS_ORIGIN is unset, or lists only origins you trust.
  • DCR is off, or on only while a client registers. --enable-dcr-insecure is never used on an internet-facing server.
  • Cloud services use OAuth clients with the smallest scopes that work, not bearer tokens.
  • Every agent has its own named token or client, so you can revoke one without breaking the rest.
  • NEXUS_BRAIN_ADMIN_BOOTSTRAP_TOKEN is a long random value kept out of logs, and --log-full-params is off.
  • You check the Agents page from time to time and revoke anything you no longer recognise.

08Troubleshooting

The server prints "[serve-http] WARNING: --public-url is set but --bind is not" and remote clients cannot connect.

The server is still listening on 127.0.0.1 only. Restart it with --bind 0.0.0.0 (or a specific interface IP) as well as --public-url.

The server prints "[serve-http] WARNING: --bind 0.0.0.0 is set but NEXUS_BRAIN_HTTP_CORS_ORIGIN is unset."

This is informational. Browser requests from other origins are refused until you set NEXUS_BRAIN_HTTP_CORS_ORIGIN. Set it only if a browser-based client needs access.

The server refuses to start with "NEXUS_BRAIN_ADMIN_BOOTSTRAP_TOKEN must be at least 32 chars and match [A-Za-z0-9_-]+."

Replace the value with a longer random string made of letters, digits, _ and -, then start the server again.

A client that registers itself fails with "client_credentials grant is not permitted via dynamic client registration".

That is the safe default. Register the client yourself with nexusbrain auth register-client <name> --grant-types client_credentials --scopes read, or let it use the consent-based authorization_code grant. Only use --enable-dcr-insecure on a trusted network.

nexusbrain auth register-client stops with "Unknown scope".

Only read, write, admin, sources_admin, users_admin and agent are accepted. Separate several scopes with spaces in quotes (--scopes "read write") or with commas (--scopes read,write).

An agent gets invalid_client with "Client has been revoked" or "Invalid client".

The client was revoked or its secret is wrong. Register a new client and update the agent with the new client ID and secret.

nexusbrain auth revoke-client says "No client found with id".

Check the ID on the Agents page of the admin dashboard. Client IDs start with nexusbrain_cl_. For a bearer token, use nexusbrain auth revoke "<name>" instead.