Skip to main content
A Cluster is an optional group of Nodes with one name, at most one development TLD, and one Router. A Node outside a Cluster is standalone. Active membership gives a Node’s Project Routes and analytics tracking hosts Cluster scope, so private traffic reaches them through the Router instead of the workload Node directly. Custom proxy Routes stay on their Node. The Routes reference owns domain generation, routing scope, and Router transition ownership. Private DNS owns which Router address a requester receives.

Commands

Every command accepts --json. Cluster and Node arguments are numeric IDs. The CLI refuses another Cluster value with cluster.id_invalid. Human lists use uppercase table headers, and one Cluster uses a detail tree. TLDs display with a leading dot; missing values display an em dash. Requests show progress while waiting and retain their Gateway request ID. Destructive Cluster commands take --force as consent. The confirmation names the resolved Cluster and the affected Node when detaching a member. Interactive confirmation starts at No. Declining, Ctrl-C or EOF stops before mutation. A pipe or --json never supplies consent and requires --force. A new Cluster is inactive. Membership, name, and TLD can be prepared while it is inactive without changing any traffic. Activating a Cluster that has a TLD, or giving an active Cluster a TLD, is the routing cutover: it requires exactly one active Router and reconciles every affected Route before the change becomes authoritative.

Placement and TLDs

A Node belongs to at most one Cluster. A standalone Node is a full placement, not a step toward a Cluster. An Instance never selects a Cluster: its routing scope follows its Node. Joining a Cluster adds no role. Leaving it removes only a router assignment of the Node that never became active, as cluster:node:remove describes. A Node keeps its own TLD while it belongs to a Cluster, and membership never changes it. While the Cluster is active and has a TLD, that TLD wins for generated domains. Otherwise the Node TLD applies. Routes owns domain generation. An inactive Cluster owns no TLD, so it can share one with any Node. Prepare a Cluster with the TLD of a Node that joins it later, and activate it after the Node joins. A member Node can keep the same TLD as its active Cluster, because both name one routing scope.

orbit cluster:create

Create a Cluster in the inactive state.
The CLI refuses a TLD that is not one lowercase DNS label with cluster.tld_invalid before it sends a request. Placement and TLDs lists the ownership rules.

orbit cluster:list

List every Cluster with its state, TLD, Router, and member Nodes.

orbit cluster:show

Show one Cluster.

orbit cluster:update

Change the name, TLD, or state of a Cluster. At least one option is required.
Activating a Cluster that has a TLD, or setting a TLD on an active Cluster, makes the Gateway check that one active Router exists, that no non-member Node owns the proposed TLD, and that every affected Route keeps a valid domain, scope, and target. Generated domains then use the Cluster TLD even when member Nodes have their own TLDs. The Gateway then republishes DNS and Router projections before it stores the change. A failure leaves the previous state authoritative. A name change alone touches no traffic.

orbit cluster:node:add

Attach an active Node to a Cluster.
Attaching to an inactive Cluster records membership and leaves Node routing and generated domains unchanged. Attaching to an active Cluster without a TLD uses Cluster scope and keeps generated domains on the Node TLD. Attaching to an active Cluster with a TLD moves generated Route domains into that Cluster namespace and Cluster scope before membership becomes authoritative. Custom proxy Routes on the Node keep Node scope and keep serving. node:add --cluster=ID attaches a Node during provisioning with the same guards.

orbit cluster:node:remove

Detach a Node from a Cluster. Routes on that Node return to Node scope before membership ends. Generated domains fall back to the Node TLD. The Gateway deletes the Node’s router assignments that never became active. Any other router assignment blocks the detach with cluster.router_detach_forbidden.

orbit cluster:router:set

Set or replace the Cluster Router. The Router must be an active member Node.
Replacement keeps the current Router active until its replacement is ready, promotes the candidate, and then cleans up the old assignment. Each Cluster has one Router operation owner. A concurrent Router change on the same Cluster waits up to 30 seconds and then fails with cluster.router_busy. A replacement that another Router change left unfinished fails with cluster.router_transition_conflict. A Node that is not an active member fails with cluster.router_node_invalid.

orbit cluster:router:unset

Clear the Router from a Cluster that is inactive or has no TLD.
The Gateway refuses to clear the Router while the Cluster owns a Route (cluster.routes_require_router) or while the Cluster is active with a TLD (cluster.active_router_required). Deactivate the Cluster or remove its TLD first.

orbit cluster:destroy

Remove an empty Cluster.
The Gateway refuses a Cluster that still has member Nodes (cluster.not_empty) or still scopes Routes (cluster.has_routes).

Why it works this way

These reasons explain the design. Check them before you propose a change.

Standalone Nodes

A useful one-Node fleet needs no Cluster, Router, or Ingress. A mandatory Cluster would make grouping a step before the first workload. So a Node can join a Cluster later, and its Instances keep their source and placement.

The Node keeps its TLD

The Node TLD is the fallback when the Cluster becomes inactive, loses its TLD, or the Node leaves. Deleting it at attach time would leave detach with no namespace to return to.
  • node provisions the Nodes that join a Cluster and assigns the router and ingress roles.
  • route creates explicit Routes with Cluster scope.