- Container images — delivered through the ManyLayers private registry (pull credentials provided during onboarding) or as an offline image archive (
manylayers-images-<version>.tar) for air-gapped environments. - Deployment assets — the
infra/docker/compose stacks (dev,demo,prod) with their.env.<stack>.exampletemplates, and a Helm chart (manylayers-<version>.tgz). - A license file — a signed
license.jsonissued for your seat count and term. See On-prem license.
Your ManyLayers account contact provides release bundles, registry credentials, and license files. Contact support if you have not received onboarding credentials.
Prerequisites
Confirm your environment meets the requirements. At minimum you need Docker Engine 24+ with Compose v2, or a Kubernetes 1.27+ cluster with Helm 3 for the Kubernetes path.Load the container images
- Private registry (internet-connected)
- Air-gapped (offline archive)
registry.manylayers.ai/manylayers/* images and pull them automatically on first start.Docker Compose installation
The recommended single-host installation. Three stacks ship in the bundle, one per environment, each a single compose file with a single env file beside it — so there is no way to end up running two databases for one deployment:| Stack | Compose file | Env file | What it is |
|---|---|---|---|
prod | infra/docker/docker-compose.prod.yml | .env.prod | Install this one. Registry images, read-only root filesystems, resource limits, data stores bound to 127.0.0.1 |
demo | infra/docker/docker-compose.demo.yml | .env.demo | An evaluation stack: baked credentials and a local mock upstream, so it runs with no provider account at all |
dev | infra/docker/docker-compose.dev.yml | .env.dev | Builds from source. For contributors, not deployments |
--env-file resolves ${VAR} inside the YAML, and env_file: injects the same values into every container. One file, one truth.
Set the environment
MANYLAYERS_ADMIN_KEY, POSTGRES_PASSWORD and REDIS_PASSWORD — compose refuses to start without them — and repeat the two passwords inside DATABASE_URL and REDIS_URL. A .env file has no variable expansion, so those URLs carry the credential literally; rotate a password and you must change it in both places.Configure the gateway
The stack mounts
configs/gateway.container.yaml read-only at /etc/manylayers/gateway.yaml. Edit it for non-secret settings — routing, cache, audit, PII, model list.Two rules govern that file: it holds no secrets, and no per-deployment values. database.url, redis.url and the listen port are ${DATABASE_URL}, ${REDIS_URL} and GATEWAY_PORT, all set from infra/docker/.env.prod, so one image runs in every environment. Credentials stay ${ENV_VAR} references resolved from the process environment — put their values in infra/docker/.env.prod:MANYLAYERS_CONNECTOR_KEY— passphrase for connector credential storage- provider keys such as
OPENAI_API_KEYandANTHROPIC_API_KEY - the path to your mounted
license.json
Start the stack
make prod-pull, make prod-migrate, make prod-up — or make prod-deploy for all of them plus a readiness check.Migrations are not left to chance: the one-shot migrate service applies the Goose set and exits, and every service waits for it to exit successfully. No long-running binary migrates on startup, so several gateway replicas booting together cannot race each other.The gateway listens on 8180 and is the only service published on all interfaces. The workspace serves the admin dashboard at http://<host>:8190/ui/ and the deployer runs on 8200; both bind 127.0.0.1, so reach them through your ingress or a VPN.Evaluating with the demo stack
To try ManyLayers before wiring in a provider, start the demo stack instead. It pulls:demo images and routes every logical model at a bundled mock upstream, so it needs no provider account, no API key and no outbound network:
make up-demo.) Its credentials are baked into the committed template by design — never expose the demo stack publicly.
Optional infrastructure services
These are in the dev stack behind theoptional profile. To run one without the rest of the stack, name it on the command line — that starts the service even though it is behind a profile:
| Service | Host port | Use case |
|---|---|---|
redis | 6479 | Shared rate limits, budgets and cache. Always started; never behind a profile |
kafka | 9192 | High-throughput queueing for queue.backend: kafka |
qdrant | 6433 | Vector store for knowledge bases and semantic caching |
minio | 9100 / 9101 | S3-compatible storage for model artifacts |
dstack | 3100 | Managed model deployments via dstack (starts its own database too) |
Production checklist
- TLS termination via a reverse proxy (nginx, Caddy, or your load balancer)
- Postgres backed by durable storage with scheduled backups
MANYLAYERS_ADMIN_KEYstored in your secret manager, not in shell history- License file mounted read-only into the gateway container
Kubernetes (Helm) installation
Key Helm values
| Value | Default | Description |
|---|---|---|
replicaCount | 1 | Set >1 with Redis configured for shared rate-limit state |
image.registry | registry.manylayers.ai | Override for internal image mirrors |
qdrant.enabled | false | Deploy an in-cluster Qdrant instance |
kafka.enabled | false | Enable the Kafka queue backend |
deployer.enabled | false | Enable managed model deployments |
deployer.mode | kubernetes | kubernetes or dstack |
Set
config.database.url to your Postgres connection string and config.redis.addr to share rate-limit and budget state across replicas.values.yaml file inside the chart archive.
Upgrading
- Load the new release’s images (registry pull or
docker load). - Re-run the migration job — migrations are forward-only and safe to apply before restarting.
- Restart the gateway with the new image tag (
docker compose up -dorhelm upgrade).
Next steps
- Quickstart — create your first team and gateway key
- Configuration reference — full
gateway.yamlwalkthrough - On-prem license — install and verify your license