Skip to content

Manage nodes

Mission Control manages the estate: which machines exist, which of them are nodes, which versions each one holds, and which is holding the write. This page is the vocabulary. There are five verbs, and only the last one removes anything.

iswhere it appears
machinean address you can reach by SSH, holding nothing of oursthe lower list
nodeHelix on a machine: a home, a release area, perhaps a worldthe upper list
modethe role a node plays — replicant, standby, multiplexor, solo — which is what you start it ason its card
environmentwhere it is running, a name the client chooses (live, test, …)on its card
versiona core and a client bundle togetheron its card

A version is always the pair. The bundle states the core it was built against in its own manifest, so naming one version resolves both halves — which is why you choose an artefact rather than a core tag. A tag alone can only ever set half of it, and half is how a core ends up under a bundle built for something else.

raw ──install <version>──▶ installed ──start [version]──▶ running
◀──uninstall (last)── ◀──────stop────────
verbwhat it doesthe world
checkasks a machine what it is, what it holds and what is offered to it. An observation, not a changeuntouched
install <version>makes a machine hold a version: places the agent if it has none, brings the artefacts in, deploys themkept
start [version]runs it as a role, at a version confirmed here. Joining the cluster is part of startingkept
stopstops it. It stays a node, with its world and its place in the setkept
uninstall <version>removes that version. The last one takes the node with itkept, except the last

Every state is observed, never believed: a card shows what the last check and the live heartbeats actually found, which is why an action re-checks the machine as soon as it finishes.

A node whose launcher was killed outright — a harness timing a test out, a terminal closed, a machine losing power mid-run — can leave its container running, because nothing can run in a process that has been killed. The next start normally clears it: each run records its container against its launcher, and a later run removes a container whose launcher is gone.

That record can be lost too, though, if whatever cleans up between runs takes the temporary directory with it. So a single-node start — demo, dev, tuning and a spiral feed — also asks the container runtime what is holding the ports it is about to publish. A container of this node’s own name is a previous run of itself, and is removed with a line saying so. Anything else is left strictly alone and the start refuses, naming what is in the way: it may be another account’s work, another product, or a member of a different cluster, and none of those are Helix’s to end.

Cluster roles are deliberately excluded. On a machine running a replicant, multiplexor or standby, a container holding a port may be a live member of the set, and clearing it down would take a node out from under a running cluster. There, a port conflict is reported and left to you.

This only ever arises on a port you named. An unnamed port is chosen from the free ones at start, so it cannot collide; what collides is HELIX_PORT, HELIX_PUBLIC_CRUD_PORT, or the MongoDB port once it has been recorded in a node’s helix.env.

A node joins the cluster as it starts, because the mode it starts as is what decides its membership — its votes, its priority, and whether it can ever be elected. Those flags apply at the moment it joins and only then, so the node joining is the only thing that can set them correctly.

If a join does not take, the card says so — running, but outside the set. Stop it and start it again. Nothing is lost by restarting a node that is outside the set, because a node outside the set is not replicating.

A node installs the version the console’s node runs. So the estate converges on one version — and that leaves the question of how a newer one arrives.

A release is pulled, never pushed. Devops gives an account a staging directory beside its release area, usually a symbolic link to an earlier environment’s release directory, so the artefact names and shapes are identical by construction. Nothing is pushed into a test or production account by whoever built the release; the account takes what it has been offered. There is no credential anywhere in this.

~/HelixRuntime/
<stem>/ a node: its launcher, its pins, its storage
release/ what this machine holds — shared between the nodes on it
staging/ what devops offers this account → usually a symlink

A machine’s card shows both, and the difference between them is what an import does:

Holds: HRA 0.2.15 · core 0.0.14ag [Uninstall]
Offered: HRA 0.2.16 · core 0.0.14ah [Import]

Importing changes nothing that is running. It copies artefacts into the release area and stops there, so a version can be brought to a live node at no cost and left sitting until somebody chooses it. That is what makes rolling an estate forward node by node, in your own time, free until the moment of choosing.

From a shell on that machine, the same thing:

Terminal window
./helixctl import # what could be taken in
./helixctl import helix-hra-0.2.16.tar # take that one

The version is confirmed when a node starts, which is also why changing it means stopping first: the SPA is served out of the core image, so a browser holding a half-loaded page against a swapped core would be running two versions at once. Mission Control refuses to swap software under a live node for the same reason.

The start control offers every version that machine holds, defaulting to the newest for this cluster’s client — not merely the newest file, since a release area is shared between the nodes on a machine and may hold another client’s bundles. As pinned leaves it on the version it already has, which is every ordinary restart.

Starting at a version pins that core, obtains it — from the machine’s own release area if the archive is there, otherwise the registry — deploys the client, and then starts. Core before bundle, always: a deploy compares the bundle against the core the node already has and refuses first, so a bundle cannot “wait” for a core to arrive later.

Going back is the same act. A rollback is starting at an older version that is still in the release area. The one thing to know is that it can be refused, and by design: once a world has been written by a newer core, an older one will not open it — it stops at boot and names both versions rather than damaging data. The primary’s card shows what the world is stamped at and what the running build reads, so you can see that before you try it.

Changing the version of the node holding the write takes Mission Control down with it, because the console runs on the writer. So either do that node last, or hand the write over first:

  1. Step down the writer, which moves both the write and the console to another node.
  2. Roll the node that is now a secondary.
  3. Repeat, ending with the node that was the writer.

That is the same order the cluster procedure has always wanted — secondaries first, one handover, the old writer last — and it is one election rather than one per node.

The only verb that removes anything, and it has two cases that differ sharply.

any versionthe last one
that version’s artefactsremovedremoved
its core imageoffered to the prune, which keeps anything pinned, in use, or recentthe same
the worldkept — you may be rolling back to itremoved, with the node’s storage and home
the launcher and the agentkeptremoved
the replica setuntouchedleft first, so the set never holds an entry for something being destroyed
this console’s cardkeptremoved

So a version removal is ordinary and reversible; the last one turns the node back into a machine and cannot be undone. The console says which one you are about to do, in those words, and asks you to confirm the machine’s own name for the second.

Removing the agent is safe. Placing one needs only SSH, so a machine carrying neither agent nor launcher is still reachable and still installable. Leaving it behind would mean a machine we have finished with still answering as a node.

It works on a machine that has died. Leaving the set is a reconfiguration performed by the writer, so it needs no answer from the machine being removed — which matters, because a failed machine that is still a voting member can stop the survivors reaching a majority.

statewhat you can do
runningStop · Check · Import · Uninstall a version it is not serving
installed, not startedStart <role> at a version · Re-install · Import · Uninstall · Check
rawInstall · Check
an install that failedRemove · Check — with the reason it failed

A node’s mode is not editable. A node is started as something, and the cluster’s view of a member must not be able to disagree with the software actually running there. Changing it is a stop and a start.