The most honest sentence in Mooring's documentation is a design constraint stated as a security oath: hosting Mooring must never be the thing that gets your server hacked. The project — a single static Go binary, roughly 12–18 MB, that turns a plain Linux server with Docker into a small Heroku — is the sharpest statement yet of a philosophy the self-hosted PaaS world keeps circling back to: the less machinery between your git repo and your running container, the less there is to break, patch, or exploit.
Mooring deserves a serious look on those terms. You describe a multi-service app in one typed mooring.yaml in your repo, connect the repo, and Mooring generates and owns the Compose file and Dockerfile underneath — you never hand-write either. It owns the public edge (Caddy with automatic HTTPS on ports 80 and 443), watches app health, and gives you a dashboard plus CLI for deploys, logs, secrets, alerts, and backups. No Swarm. No Kubernetes. One binary, one server, one file per app.
This post takes that pitch at face value, then asks the question every one-box PaaS eventually faces: what concretely breaks the day you need a second server? Here is the whole answer up front — a capability-by-capability accounting of the no-orchestrator tradeoff across Mooring, Coolify, Dokploy, and a fleet-native Cluster API platform — with the evidence and the decision rule in the sections below.
| Capability at machine #2 | Mooring | Coolify | Dokploy | Fleet-native (Cluster API) |
|---|---|---|---|---|
| Provision machine #2 | Manual: install binary, repeat setup by hand | Manual: add SSH host in UI, agent per host | Join Swarm worker to the cluster | Declarative: a Machine object, controllers do the rest |
| Schedule work across machines | Not possible: replicas live on the one box | Per-host only: each host is a separate island | Yes: Swarm schedules services across nodes | Yes: scheduler + autoscaler across the fleet |
| Survive losing a machine | No: the box is a single point of failure | No per app: an app lives on its host | Partial: Swarm reschedules stateless replicas | Yes: controllers reschedule; etcd quorum survives one loss |
| Edge and TLS across machines | One Caddy per box, no shared routing | One proxy per host, no shared routing | Traefik ingress routing across the Swarm | Ingress + external LB, declarative and shared |
| Stateful data across machines | Lives on the box's disk; you back it up | Lives on the app's host disk | Swarm volumes; multi-node state still on you | CSI volumes, snapshots, topology-aware placement |
| Fleet-wide upgrades | One box at a time, by hand | Host by host in the UI | Rolling service updates via Swarm | Rolling machine rollout, declarative |
| Security posture | Secure-by-default single box, documented threat model | Hardening is operator-owned per host | Hardening is operator-owned per node | Fleet trust: RBAC, network policy, signed supply chain |
The short version: Mooring wins the first deploy on simplicity and secure defaults; the tradeoff it makes — no orchestrator — becomes the bill you pay at the second machine. The rest of this post shows exactly where that bill lands.
What "no orchestrator" actually means
Mooring's architecture diagram fits on one line: typed YAML → Mooring control plane → Docker Engine. There is no scheduler, no cluster membership, no node lifecycle. Mooring talks to the Docker Engine on its own host, generates Compose files from your mooring.yaml, and runs them. Its own docs frame the product as "[m]any apps on one server" — horizontal in apps, vertical in machines: exactly one.
This is not the same as having no automation. Mooring ships thoughtful single-box automation that a raw docker compose up never gives you: safe deploys from git with pre-flight checks and automatic rollback, a self-healing supervisor that recovers failed services, and per-service auto-scaling that watches CPU, memory, queue depth, or edge-measured p95 latency. But every one of these automations is bounded by the box. The auto-scaler only adds a replica when the host provably has room, moves one step at a time, and collapses a service back to a single replica when the server fills up — at which point it alerts you that, in effect, you need a bigger box. There is no "spill over to machine #2" because machine #2 does not exist in Mooring's world model.
That boundary is a feature, not an oversight. No orchestrator means no Raft quorum to maintain, no overlay network to debug, no control-plane upgrades to schedule, and a ~12–18 MB binary with no database or companion services to operate. Mooring runs its write plane on servers with as little as 1 GB of RAM. The entire operational surface is one file you can replace to upgrade and one systemd service to watch. For a solo developer or a small team running a handful of apps, that is a genuinely compelling trade — which is exactly why the tradeoff deserves precise accounting rather than dismissal.
What "security-first" concretely buys on one box
"Security-first" is doing real work in Mooring's pitch, so it is worth itemizing rather than waving at. The mechanisms are specific: the dashboard is private by default (loopback plus IP allowlist), secrets are encrypted at rest and referenced by name so they never sit in the repo or logs, git access is fetch-only through read-only deploy keys, a push can never deploy itself, and an unsafe configuration makes Mooring refuse to start rather than run insecure. Privileged actions flow through an audited API with scoped tokens, backups are encrypted, and the whole posture is written down in a documented threat model. The project's own comparison table credits its rivals with only partial coverage here — "best-effort as of 2026," the README cautions — but the concrete list above is verifiable in Mooring's own docs regardless of how the neighbors compare.
The honest boundary of that posture is the box itself. One-box secure-by-default solves the problem "this server must not get owned through its PaaS." It does not solve — because it does not attempt — the problems a second machine introduces: how nodes authenticate to each other, how tenant traffic is segmented across hosts, how the control plane's own components are versioned and verified fleet-wide. Fleet security is a strictly larger problem (mutual node trust, network policy, etcd encryption, signed provider supply chains), and a platform that never has a second node never pays for it. That is the cleanest statement of Mooring's bargain: it shrinks the security problem to the smallest shape it can take — one hardened box — and solves that shape thoroughly.
The second-server moment: where the bill lands
Now walk the table row by row, because "no multi-machine support" undersells how many distinct capabilities a second server demands.
Provisioning. Adding machine #2 to Mooring means repeating the install by hand: provision the server, install Docker, install the binary, generate credentials, configure the edge — a snowflake assembly line. Coolify improves the ergonomics (register the host over SSH in one UI) but each host remains separately managed. Dokploy goes furthest here by joining the machine to a Swarm, after which the cluster knows about it. A Cluster API fleet inverts the model entirely: you declare a Machine object and controllers converge reality to match, which is also what makes machine #2 identical to machine #20.
Scheduling and rescheduling. This is the row that bites first in practice. Mooring's auto-scaler is excellent within one box and nonexistent across two: when the box is full, the answer is a bigger box. Coolify's hosts are islands — an app lives on its host, and a full host means manual migration. Dokploy's Swarm actually schedules services across nodes and reschedules stateless replicas when a node dies, which is the one capability in this table where the Swarm-backed middle ground genuinely answers the question. Fleet-native platforms add bin-packing, topology awareness, and autoscaling on top.
Surviving a dead machine. A Mooring box that dies takes every app on it down until the box — or its backup on a fresh box — comes back. Same for a Coolify host and its apps. Swarm reschedules stateless work but leaves stateful recovery to you. Only the fleet model treats machine death as routine: controllers notice, reschedule, and reprovision without an operator driving.
Edge, state, and upgrades follow the same gradient. Each one-box tool runs its own edge per machine with no shared routing; state lives on local disks with backups as the durability story; upgrades are per-box affairs. Swarm gives Dokploy rolling service updates and shared ingress routing — real answers, one rung up. The fleet model answers all three declaratively: shared ingress, CSI-backed volumes with snapshots, rolling machine upgrades driven by the same reconciliation loop as everything else.
None of this is news to the Mooring author, whose docs never pretend otherwise. The point of the itemization is to replace a vague "doesn't scale" with a specific shopping list: the day you need machine #2, you need provisioning, scheduling, rescheduling, shared edge, shared state, and fleet upgrades — six capabilities, not one — and you will be building, buying, or migrating to each of them separately.
Where the Swarm-backed middle ground actually lands
Coolify and Dokploy are often lumped together as "the single-server PaaSes," but on the second-server question they sit in different places, and the difference matters.
Dokploy is Swarm-native: its multi-server story is a real Swarm cluster with Traefik ingress routing, which means cross-node scheduling, rescheduling, and rolling updates genuinely work. If your growth path tops out at "a few machines behind one edge," Dokploy's answer is coherent and complete.
Coolify manages SSH-connected standalone hosts — one UI over many islands — with Swarm support still experimental. That is better ergonomics than Mooring's one-binary-per-box (single pane of glass, shared build configuration), but architecturally it is N one-box deployments, not one N-box deployment. An app still lives on exactly one host.
The question hanging over both is Swarm's own trajectory. The facts are better than the rumors: Mirantis committed to supporting Swarm through at least 2030, Swarm mode still ships in every Docker Engine, and the September 2026 Engine release (29.8.0) carried seven Swarm fixes. But "supported" is not "invested in" — Swarm is in long-term maintenance while orchestration innovation (device scheduling, topology awareness, declarative machine lifecycle) happens in Kubernetes and Cluster API. Betting a growth path on Swarm in 2026 means betting that maintenance-mode orchestration is all you will ever need past one box. For many teams that bet wins. It should just be placed with eyes open: the ceiling is a stable, frozen feature set, not a growing one.
When the tradeoff flips: a decision rule
Abstract tradeoffs become useful as a checklist. Stay on one box — and Mooring is arguably the best-executed version of that choice right now — if all of these hold:
- Your workload fits one machine with headroom: a few apps, state that fits one disk, traffic one Caddy can terminate.
- One operator (or a small team with shared context) runs the platform; nobody needs tenant isolation or delegated access.
- You can tolerate the box as a single point of failure: backups plus a documented restore runbook meet your recovery objective.
- Your growth plan is vertical: when the box fills, you resize it, and you have a rough idea where that stops working.
Start planning the move — to Swarm-backed tooling or straight to a fleet-native platform — when any of these appear:
- You are provisioning machine #2 for capacity, redundancy, or geography rather than resizing machine #1.
- Two workloads need to not trust each other: per-tenant network isolation, resource quotas, or separate access control.
- Deploys need to survive the platform itself being upgraded: zero-downtime platform upgrades, not just zero-downtime app deploys.
- Your workload mix outgrows uniform containers: GPUs, specialized scheduling, batch queues, or stateful topologies.
The typical stay-put workload is concrete: a side project, an agency hosting client marketing sites, an internal toolset, a pre-product-market-fit startup running its whole stack in one place. The typical move-on workload is equally concrete: the SaaS that just signed the customer whose contract requires multi-AZ redundancy, or the team whose staging-plus-prod no longer fits the biggest single box they will pay for. Most teams know which side they are on; the checklist just stops the migration conversation from starting two machines too late.
One box, done right — and the seam it can't cross
Mooring is the strongest version of an old idea: that the first deploy should be nearly free, nearly instant, and secure without a hardening project. A single binary, a typed YAML, generated Compose files you never touch, HTTPS that just exists, git deploys that roll back, secrets that stay encrypted — it is a complete answer to "I have a server and a repo, now what," and its security posture is more carefully reasoned than anything else in its weight class. If that is your whole problem, the orchestrator conversation is pure overhead and Mooring is right to skip it.
But a control plane that models exactly one machine has a seam, and the seam is machine #2. Not one capability but six — provisioning, scheduling, rescheduling, shared edge, shared state, fleet upgrades — each of which the one-box world answers by hand, the Swarm world answers partially, and the fleet-native world answers declaratively. Secure-by-default on one box is a different product than fleet-native from day one, and the honest move is to pick the product whose seam you will not hit — or to know, going in, what crossing it will cost.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



