Skip to content

Docker Compose Installation

This guide covers installing Mantis using Docker Compose.

  • Docker 24.0+
  • Docker Compose 2.20+
  • Git
Terminal window
git clone https://github.com/MantisPlatform/mantis.git
cd mantis
Terminal window
# Copy the example environment file
cp .env.example .env
# Generate the three keys it ships empty
sed -i "s|^MANTIS_ENCRYPTION_KEY=$|&$(openssl rand -base64 32)|; s|^MANDIBLE__SECURITY__TOKEN_LOOKUP_KEY=$|&$(openssl rand -base64 32)|; s|^MANTIS_METRICS_TOKEN=$|&$(openssl rand -hex 32)|" .env
# Edit configuration
nano .env
Terminal window
# Generate development certificates
just dev-certs
Terminal window
# Start the core services (postgres, rabbitmq, mandible, thorax; redis follows
# transitively). Lens is NOT included -- it is gated behind the "ui" profile.
./docker.sh start
# Start the Lens UI
docker compose --profile ui up -d lens
Terminal window
./docker.sh db-migrate

Open https://localhost:5173 in your browser (this requires the Lens UI to be running — see the ui profile step above).

Default credentials:

The first sign-in with this password asks for a new one and serves nothing else until it is set: the default is published.

Mantis uses Docker Compose profiles for different deployment scenarios:

ProfileDescriptionCommand
defaultCore servicesdocker compose up
devDevelopment tools (PgAdmin, etc.)docker compose --profile dev up
uiInclude Lens UIdocker compose --profile ui up
with-clientInclude Tarsus agentdocker compose --profile with-client up
multi-thoraxMultiple Thorax instancesdocker compose --profile multi-thorax up
toolsDevelopment tools only (Mailpit, PgAdmin)docker compose --profile tools up
thumbprintTarsus agents in thumbprint TLS modedocker compose --profile thumbprint up
scalingSecond Thorax instance, as multi-thoraxdocker compose --profile scaling up
aiOllama, for local AI analysisdocker compose --profile ai up
prodLens plus Ollamadocker compose --profile prod up

docker compose config --profiles prints the list straight from the compose file if a service is added after this page was written.

Terminal window
./docker.sh status
# or
docker compose ps
Terminal window
# All services
./docker.sh logs
# Specific service
./docker.sh logs mandible
Terminal window
./docker.sh restart
Terminal window
./docker.sh stop
Terminal window
# Database
POSTGRES_USER=mantis
POSTGRES_PASSWORD=<strong-password>
POSTGRES_DB=mantis
# JWT (RS256 — generated by just dev-certs)
# Container-internal paths (the host ./.keys/ dir is mounted at /etc/mantis/keys/)
MANDIBLE__JWT__PRIVATE_KEY_PATH=/etc/mantis/keys/jwt-private.pem
MANDIBLE__JWT__PUBLIC_KEY_PATH=/etc/mantis/keys/jwt-public.pem
# Encryption
MANTIS_ENCRYPTION_KEY=<32-byte-base64-key>

See Environment Variables for complete reference.

Verify services are healthy:

Terminal window
./docker.sh health

Or check individual endpoints:

Terminal window
# Mandible API. -k because the compose certificate is signed by the dev CA
# `just dev-certs` generated, which no system trust store carries.
curl -k https://localhost:3000/api/v1/health
# Thorax. Its gRPC port requires a client certificate, and compose does not publish
# the plain-HTTP health listener to the host, so what is checkable from here is that
# the gRPC port accepts TCP -- the same probe `docker.sh status` makes.
timeout 3 bash -c '</dev/tcp/127.0.0.1/50051' && echo 'thorax accepting connections'
# For the health document itself, ask from a container that shares the network and
# ships an HTTP client. The compose file binds Thorax's listener to 0.0.0.0:9090 inside
# the container -- reachable across the compose network, never published to the host --
# and it answers only to MANTIS_METRICS_TOKEN, which Mandible holds as its own metrics
# token. The thorax image itself carries no curl or wget.
docker compose exec mandible sh -c \
'wget -qO- --header "Authorization: Bearer $MANDIBLE__METRICS__AUTH_TOKEN" http://thorax:9090/health'
  1. Check Docker daemon is running
  2. Verify ports are available
  3. Check logs: ./docker.sh logs
  1. Verify PostgreSQL is healthy
  2. Check DATABASE_URL configuration
  3. Ensure migrations have run
  1. Regenerate certificates with just dev-certs --force and restart the stack (it replaces the CA and every key)
  2. Verify certificate paths in .env
  3. Check certificate validity dates