Skip to main content
Run the full Manifest stack on your own machine. No Node.js required, just Docker. To run Manifest somewhere other than your own machine, see the other self-hosting paths. All three paths end in the same place: a running stack at http://localhost:2099 where you sign up. The first account you create becomes the admin. No demo credentials are pre-seeded.
The bundled compose file binds port 2099 to 127.0.0.1 only, so the dashboard is reachable on the host machine but not over the LAN. See Exposing on the LAN to change this.

Installation

First request

Signing up leaves you with an empty instance. Three steps to a routed request.
1

Connect a provider

In the dashboard sidebar, open Providers and pick how you want to connect:
  • Usage-based — paste an API key (OpenAI, Anthropic, Gemini, DeepSeek, …)
  • Subscriptions — reuse a plan you already pay for (ChatGPT, Claude, GLM Coding Plan, …)
  • Local — Ollama, LM Studio, or llama.cpp running on the host
Manifest discovers the available models as soon as the connection is saved.
2

Copy your agent's key

Every agent has its own key, shown when you create it and again under the agent’s Settings. It starts with mnfst_.
3

Send a request

The endpoint is OpenAI-compatible, so any SDK or agent that accepts a base URL works — point it at http://localhost:2099/v1 with the mnfst_ key. To check it end to end:
"model": "auto" asks Manifest to route the request. Any other name is treated as an explicit choice, and falls back to your routing config if it matches nothing you have connected.
The request shows up in the dashboard straight away, with the model that served it and what it cost.
Errors raised by Manifest itself carry an M### code, a plain-English cause, and a link to the matching page under manifest.build/docs/errors. The three you are most likely to see on a fresh install:

Verifying the image signature

Published images are signed with cosign keyless signing (Sigstore). Verify before pulling:

Custom port

If port 2099 is taken, set PORT in .env. That is the whole change:
The compose file reads ${PORT:-2099} for both the published host port and the backend’s internal listener, and BETTER_AUTH_URL defaults to http://localhost:${PORT:-2099} — so one line covers all three, with no YAML edit. The install script writes it for you if you pass --port 8080. For a docker run install there is no .env, so pass the mapping and the URL explicitly. The container keeps listening on 2099 and Docker remaps it:
If you see an “Invalid origin” error on the login page, BETTER_AUTH_URL doesn’t match the URL you’re accessing the dashboard on. The host matters as much as the port.
Upgrading from a pre-2099 install? Your existing stack keeps running on port 3001 with no changes — the backend’s own fallback is still 3001, so the new image works against your old compose file. If you want to refresh your compose file but stay on the legacy port (to avoid reconfiguring OAuth callbacks, reverse proxies, or bookmarks), set PORT=3001 in .env and the bundled compose file will honour it for both the host binding and the internal listener.

Exposing on the LAN

By default the compose file binds port 2099 to 127.0.0.1 only. The dashboard is reachable from the host but not from other machines on the network. To expose it on the LAN:
1

Change the port binding

Edit docker-compose.yml and change the ports line from "127.0.0.1:2099:2099" to "2099:2099".
2

Set BETTER_AUTH_URL

In .env, set BETTER_AUTH_URL to the host you’ll reach the dashboard on, e.g. http://192.168.1.20:2099 or https://manifest.mydomain.com. This must match the URL in the browser or Better Auth will reject the login with “Invalid origin”.
3

Apply

Image tags

Every release is published with the following tags: Images are built for both linux/amd64 and linux/arm64.

Upgrading

Manifest ships a new image on every release. To upgrade an existing compose install:
Database migrations run automatically on boot, no manual steps. Your data in the pgdata volume is preserved across upgrades. Pin to a specific major version (e.g. manifestdotbuild/manifest:5) in docker-compose.yml if you want control over when major upgrades happen.

Backup and persistence

The stack uses two named volumes: The database volume is the one to back up. Losing the recordings volume costs you stored message bodies and nothing else, and those expire on a retention schedule regardless. Back up (from the host, with the stack running):
Restore into a fresh stack:
To list or remove the volume manually:

Environment variables

Core The first two are required and the installer generates both, so a default install boots without you setting anything.
The installer also generates MANIFEST_ENCRYPTION_KEY. If you are installing by hand, set it too. Left unset, Manifest falls back to BETTER_AUTH_SECRET for at-rest encryption and warns on every boot — meaning one leaked session-signing secret also decrypts every stored provider key and OAuth token. Set it before first boot: introducing it later means re-encrypting what is already in the database.
Everything else is optional: rate limits, provider timeouts, email delivery for alerts and password resets, OAuth logins, connection-pool sizing, recording storage and retention, Auto-fix, and Sentry. See Environment variables for the full list with defaults.
NODE_ENV and SEED_DATA are fixed by the bundled compose file and are not knobs for a self-hosted install. The image is a production artifact, and the demo-data seeder refuses to run under NODE_ENV=production whatever SEED_DATA says — use the first-run setup wizard to create your admin account.BIND_ADDRESS is likewise set by the image (0.0.0.0, so the container is reachable through Docker’s port mapping); restrict exposure with the ports line in docker-compose.yml, not this variable.

Stop and clean up

Data and privacy

Manifest always keeps metadata about each request — model, provider, tier, token counts, cost, latency. Message bodies are separate and optional: with message recording on for an agent, prompts and completions are stored too, in the recordings volume rather than the database. New agents have it enabled. See Data and telemetry.

Telemetry

Once a day, each install sends an anonymous aggregate report: version, provider mix, token and cost totals. Never prompts, keys, or anything tied to a user. Set MANIFEST_TELEMETRY_DISABLED=1 in your .env to turn it off. Full field list, what’s never sent, and how to point it at your own endpoint: Data and telemetry.

Docker Hub

The image is available at manifestdotbuild/manifest on Docker Hub.