Skip to main content
Run the full Manifest stack on your own machine. No Node.js required, just Docker. All three paths end in the same place: a running stack at http://localhost:3001 where you sign up. The first account you create becomes the admin. No demo credentials are pre-seeded.
The bundled compose file binds port 3001 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

Verify

After connecting a provider, send a test request and watch it land in the dashboard. Grab your Manifest API key from the dashboard (it starts with mnfst_) and run:
curl -X POST http://localhost:3001/v1/chat/completions \
  -H "Authorization: Bearer mnfst_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"model": "manifest/auto", "messages": [{"role": "user", "content": "Hello"}]}'
If the response comes back with That doesn't look like a Manifest key, you’re still using the placeholder — replace mnfst_YOUR_KEY_HERE with the real key from the dashboard.

Verifying the image signature

Published images are signed with cosign keyless signing (Sigstore). Verify before pulling:
cosign verify manifestdotbuild/manifest:<version> \
  --certificate-identity-regexp="^https://github.com/mnfst/manifest/" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

Custom port

If port 3001 is taken, change both the mapping and BETTER_AUTH_URL:
docker run -d \
  -p 8080:3001 \
  -e BETTER_AUTH_URL=http://localhost:8080 \
  ...
Or in docker-compose.yml:
ports:
  - '127.0.0.1:8080:3001'
…and in .env:
BETTER_AUTH_URL=http://localhost:8080
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.

Exposing on the LAN

By default the compose file binds port 3001 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:3001:3001" to "3001:3001".
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:3001 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

docker compose up -d

Image tags

Every release is published with the following tags:
TagExampleDescription
major.minor.patch5.46.0Fully pinned
major.minor5.46Latest patch within a minor
major5Latest minor+patch within a major
latestLatest stable release
sha-<short>Exact commit for rollback
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:
docker compose pull
docker compose up -d
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

All state lives in the pgdata named volume mounted at /var/lib/postgresql/data in the postgres service. Nothing else in the Manifest container is stateful. Back up (from the host, with the stack running):
docker compose exec -T postgres pg_dump -U manifest manifest > manifest-backup-$(date +%F).sql
Restore into a fresh stack:
docker compose up -d postgres
cat manifest-backup.sql | docker compose exec -T postgres psql -U manifest manifest
docker compose up -d
To list or remove the volume manually:
docker volume ls | grep pgdata
docker compose down -v    # destroys all data

Environment variables

Core
VariableRequiredDefaultDescription
DATABASE_URLYesPostgreSQL connection string
BETTER_AUTH_SECRETYesSession signing secret (min 32 chars)
BETTER_AUTH_URLNohttp://localhost:3001Public URL. Set this when using a custom port
PORTNo3001Internal server port
NODE_ENVNoproductionNode environment
SEED_DATANofalseSeed demo data on startup
Network and security
VariableDefaultDescription
BIND_ADDRESS127.0.0.1Bind address
CORS_ORIGINAllowed CORS origin
API_KEYInternal API key
AUTO_MIGRATEtrueRun database migrations on startup
Rate limiting
VariableDefaultDescription
THROTTLE_TTL60000Rate limit window in ms
THROTTLE_LIMIT100Max requests per window
Default: 100 requests per 60-second window.Email alerts (Mailgun)
VariableDescription
MAILGUN_API_KEYMailgun API key
MAILGUN_DOMAINMailgun domain
MAILGUN_FROMSender address for alerts
OAuth providers
VariableDescription
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETGoogle OAuth
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRETGitHub OAuth
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRETDiscord OAuth
Full env var reference: github.com/mnfst/manifest

Stop and clean up

docker compose down       # Stop services (keeps data)
docker compose down -v    # Stop and delete all data

Docker Hub

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