Self-Host Getting Started
PRYZM 2 ships a self-host Docker Compose stack so you can run the platform on your own Linux box with one command. Target install time: under 10 minutes on a fresh VM with warm Docker cache.
Status (S67, 2026-04-28): the stack scaffolding is complete and the compose file + Dockerfiles + install script are committed at
pryzm-selfhost/. Container images are not yet published toghcr.io, so the install script builds them locally on first run (~5–15 min). Published images + ARM64 multi-arch ship at S70.
What you get
A single Docker network with six services:
- postgres — Postgres 16, the application database.
- minio — S3-compatible storage for bake artefacts and plugin bundles.
- sync-server — collaborative editing event log.
- bake-worker — incremental geometry/scene baking.
- api-gateway — REST + WebSocket public API.
- editor — nginx serving the SPA and reverse-proxying API/WS traffic.
The user-facing front door is http://<your-host>:3000.
Prerequisites
- Linux x86_64 (ARM64 supported once published images land).
- Docker 20.10+ with the Compose v2 plugin (
docker compose) or legacy docker-compose v1. The installer detects either. opensslfor secret generation (preinstalled on every mainstream distro).- 4 GB RAM, 10 GB free disk.
Install
From a clone of the PRYZM repository:
cd pryzm-selfhost./install.shThe script:
- Detects
docker composevsdocker-compose. - Generates 24-byte hex secrets for Postgres and MinIO into
.secrets/(skipped if they already exist). - Copies
.env.exampleto.envif missing. - Builds all images (skip with
SKIP_BUILD=1once published images land). - Brings the stack up and waits for every service to report healthy.
When healthchecks go green:
- Editor:
http://localhost:3000 - MinIO admin console:
http://localhost:9001(userpryzm, password from.secrets/minio_password)
Day-2 operations
# Tail all logsdocker compose logs -f
# One servicedocker compose logs -f api-gateway
# Restart after config changedocker compose restart api-gateway
# Rebuild after upstream code changedocker compose build api-gateway && docker compose up -d api-gateway
# Stop (data preserved)docker compose down
# Stop and DELETE all datadocker compose down -vpryzm-selfhost/Makefile wraps the common ones (make up, make down,
make logs, make health, make nuke).
Secrets
Two files live in .secrets/ after install:
.secrets/postgres_password.secrets/minio_passwordBoth are mode 0600 and ignored by git. To rotate:
- Stop the stack:
docker compose down. - Generate a new value:
echo -n "$(openssl rand -hex 24)" > .secrets/postgres_password. - For Postgres, you also need to update the role password inside the
database (the password file is read on container start to seed the
superuser, but a running cluster doesn’t re-read it). Easiest path:
docker compose down -vto wipe and start fresh, OR runALTER ROLE pryzm WITH PASSWORD '<new>';against the live DB before updating the file. - Restart:
docker compose up -d.
A turnkey rotation script lands at S68 D9 (secret-rotation playbook).
Multi-region
Self-host is single-region by design. The PRYZM_REGION env var in
.env.example is reserved for future use; setting it has no effect at S67.
Multi-region SaaS hosting is a Tier-2 cut for M36 GA per
ADR-0049. EU-resident customers should run the self-host stack on an
EU-located VM (Hetzner / OVH / Scaleway Frankfurt are all good choices).
What is NOT yet in scope at S67
| Item | Lands at | Notes |
|---|---|---|
Published ghcr.io/pryzm/* images | S70 | Today, install script builds locally |
| ARM64 multi-arch | S70 | Dockerfiles are arch-agnostic; needs CI publish pipeline |
| Migration tooling | S70 | Move data from PRYZM SaaS to self-host |
| Self-host BYO-key AI safety cap | S70 | Env var present in .env.example; runtime gate at S70 |
| TLS termination at editor nginx | S70 | Today, expects upstream proxy to handle TLS |
| Single-binary distribution | post-GA | Docker Compose path stable first |
Troubleshooting
Build hangs at “Installing dependencies”
First-run pnpm install is ~2 GB. Use --progress=plain to see live
output: docker compose build --progress=plain. Subsequent builds are
fast thanks to Docker layer caching.
docker-compose: command not found
Install Docker with the Compose plugin (docker compose version works) or
install legacy docker-compose v1.
Healthcheck timeout
Bump the wait window: HEALTHCHECK_TIMEOUT_SEC=600 ./install.sh. Then
inspect docker compose ps and docker compose logs <service>. At S67,
sync-server and bake-worker /health endpoints are referenced by the
healthcheck but not yet wired into the service app.ts — until they land,
expect “unhealthy” reports for those two services. The services themselves
work correctly; they just don’t self-report.
Port 3000 already in use
Edit pryzm-selfhost/docker-compose.yml, change the editor ports: line:
"3001:80" and access at http://localhost:3001.
Filing issues
Self-host issues: file at the PRYZM repo issues page with the selfhost
label. Include docker compose ps + docker compose logs --tail 200
output.