Architecture
Mezzanine is a single SQLite-backed Express + Next.js panel that opens SSH connections out to your servers. Nothing about it is special-cased to a particular cloud — every provider integration is a thin API wrapper on top of the same primitives.
System architecture
Three containers on a single Docker network:
| Service | What it does | Image |
|---|---|---|
mezzanine-nginx | TLS terminator + routing | nginx:1.27-alpine |
mezzanine-frontend | Next.js SSR + static assets | Local build (Dockerfile.frontend) |
mezzanine-backend | Express + Socket.IO + SSH/Docker services | Local build (Dockerfile.backend) |
State lives in one named volume (mezzanine_data) mounted at /data inside the backend container. That’s the only thing you need to back up — everything else is reproducible from git + a fresh docker compose build.
Out to your fleet
For each adopted server, the backend opens one SSH connection on demand (pooled, idle-timed) and runs commands as the configured user. For each provider, it holds OAuth2 / API-token credentials in the integrations table and makes signed HTTPS calls. The control plane never sits in the data path — it configures and observes, but in-pool traffic flows browser → LB → members directly.
Code layout
mezzanine/├── backend/src/│ ├── routes/ # /api/* — thin Express handlers│ ├── services/ # business logic, SSH/Docker/provider clients│ ├── websockets/ # Socket.IO namespaces (terminal, metrics, logs)│ ├── middleware/ # auth, role-gate, response cache│ └── db/index.ts # SQLite schema + migrations├── frontend/│ ├── app/ # Next.js App Router pages│ ├── components/ # shared React components│ ├── api/client.ts # axios client + per-resource API namespaces│ └── lib/ # helpers (dialogs, workflow templates, transformers)├── samples/ # reference apps + this docs site + landing page└── deploy/ # Production artifacts (docker-compose, nginx.conf, INSTALL.md)Why SQLite?
Single-file storage trades horizontal scalability for operational simplicity:
- One file to back up.
cp mezzanine.db /backup/is your DR plan. - No DB server to provision, monitor, or upgrade
better-sqlite3is synchronous → no async ceremony around every query- Easily handles 100K runs + 10K servers on a $5 VPS
If you outgrow it (>100 concurrent users, multi-region setup), swap for Postgres — the schema is portable.