Architecture
MZPanel has two core pieces: the control plane (cloud) and the agent (on the customer VPS). The agent carries a native execution engine — site, backup, database, Docker and other operations run inside the agent itself, as a single Go binary. Nothing about MZPanel needs to be installed on your VPS except that agent.
Two operating modes, one engine
Section titled “Two operating modes, one engine”The same native engine backs both ways of working a box, so they never drift:
- Panel mode (web). You click an action in the dashboard (
app.mzpanel.com). The control plane sends the command down the agent’s WebSocket, the agent runs it natively, and the result streams back to the page. - CLI mode (on-box). You SSH into the VPS and run
mzdirectly —mz site create example.com,mz cron list --json, etc. On the box,mz(/usr/local/bin/mz) is just a friendly front-end to the very same compiled agent, so a CLI action and the equivalent panel click execute identical code.
The two modes are parallel and non-exclusive: a power user (or an on-box AI such as ClaudeCode) can drive the box from the shell while the dashboard shows the same state. See The mz CLI.
Connection model — agent dial-out
Section titled “Connection model — agent dial-out”The agent dials outbound to wss://ws.mzpanel.com:443. The customer VPS opens
no inbound ports, needs no domain, and is unaffected by NAT. Each VPS holds one
persistent WebSocket carrying:
- A heartbeat every 30s
- Status/metrics push (CPU, RAM, disk, site count)
- Commands from the web → exec natively → stdout/stderr streamed back
- Events pushed up (backup done, SSL renewed, …)
[web] app.mzpanel.com ──► api.mzpanel.com ──ws──► agent (native engine) ──► VPS ▲ │ └────────── stream ◄───────┘Because the connection is outbound-only, firewalls and NAT don’t matter — nothing ever connects to your VPS. See The agent for the process itself.
Source of truth
Section titled “Source of truth”- On the customer VPS:
/etc/mz/*— the on-VPS registry (for example/etc/mz/sites/<domain>.conf). The agent reads and writes it directly; the control plane does not keep its own copy of VPS state. Agent-local config and keys live under/etc/mzagent/. - On the control plane: Postgres stores users, orgs, servers (metadata + last-seen), licenses, and the audit log. It does not mirror full VPS state — that would drift the moment you touched the box over SSH. For fast reads, the control plane keeps a cache of what the agent last pushed, but the box always wins.
Why the public site is separate from the dashboard
Section titled “Why the public site is separate from the dashboard”This public site (mzpanel.com) is a static Astro build for fast loads, good
SEO, and AI/MCP-readable content. The dashboard (app.mzpanel.com) is a separate
SPA, and the control-plane API (api.mzpanel.com) is a third service that also hosts
the WebSocket gateway (ws.mzpanel.com). See /llms.txt for the
machine-readable docs map.
Related
Section titled “Related”- The agent — the single Go binary on your VPS.
- Security model — how the three connections are authenticated.
- Tiers & quotas — how the tier gate is enforced at connect time.
- The mz CLI — driving the box from the command line.