Skip to main content
Roll new mx-chain-go binaries across nodes. Stale upgrade locks self-heal. Downgrade by re-pointing at any cached binary tag.

Shortest commands

mxnode upgrade                              # latest tag, every node, rolling
mxnode upgrade --binary-tag v1.11.5         # pin the tag
mxnode upgrade --binary-tag v1.11.4         # downgrade — uses cached binary if present
To downgrade, pass any --binary-tag T already in the binstore. The acquirer reuses the cached binary instead of re-acquiring it, so the operation collapses to a local symlink swap + restart per node.

Options

FlagDefaultEffect
--binary-tag <T>resolved from GitHubPin the mx-chain-go tag.
--config-tag <T>leave untouchedPin the mx-chain-mainnet-config tag.
--proxy-tag <T>leave untouchedPin the proxy tag (only when a proxy is installed).
--strategy rolling|parallelrollingPer-node ordering.
--max-parallel N1Cap when --strategy parallel.
--select '<expr>'--allSelector grammar. See lifecycle.
--node NallLimit to specific nodes (repeatable).
--shard <S>allLimit to one shard.
--skip-validatorsoffSkip validator-role nodes.
--dry-runoffPrint the resolved plan without doing anything.

Examples

# Just shard 0
mxnode upgrade --binary-tag v1.11.5 --shard 0

# A single node
mxnode upgrade --binary-tag v1.11.5 --node 2

# Parallel up to 2 (faster, less safe)
mxnode upgrade --binary-tag v1.11.5 --strategy parallel --max-parallel 2

# Squad-aware upgrade (reapplies observer-shape config edits)
mxnode upgrade squad --binary-tag v1.11.5 --proxy-tag v1.3.4

# Proxy only
mxnode upgrade proxy --proxy-tag v1.3.4

Per-node steps

Each node goes through five idempotent steps:
StepWhat
ResolvingAcquire the binary into the binstore (skipped if cached)
Stoppedsystemctl stop
ConfigAppliedRe-stamp prefs.toml for squad / observer edits
BinaryReplacedAtomic symlink swap of <workdir>/node to the new tag
Startedsystemctl start
NonceVerifiedPoll the local REST API until nonce is within 5 of siblings or is-syncing == 0
Idempotency means it’s safe to re-run after a crash — every step is a no-op when the desired state is already in place.

Downgrade

upgrade --binary-tag <older> reuses the binstore if the tag is cached, making the operation a local symlink swap + restart per node. If the tag isn’t cached, mxnode re-acquires it. Pruning policy is controlled by [install].binary_keep in config.toml; the default of 3 keeps the last three tags.

Self-healing inflight.toml

Every upgrade writes a ~/.local/state/mxnode/inflight.toml lock at the start, updates current_step as the orchestrator advances, and removes it on completion. The file records:
  • op, started_at, strategy, selected nodes
  • completed nodes, current node, current_step
  • target_binary_tag, target_config_tag, target_proxy_tag
  • [identity] — owner pid + start token
Two purposes: lock (a second upgrade won’t clobber a running one) and crash breadcrumb (cat inflight.toml after a death tells you what step the upgrade died on). When mxnode upgrade starts and finds an existing inflight.toml, it classifies the recorded pid:
Pid statusmxnode behaviour
LiveRefuse — another mxnode is genuinely running.
DeadClear the file, log → clearing stale inflight.toml from previous run …, proceed.
IndeterminateSame as dead.
A crashed upgrade therefore self-recovers on the next invocation; rerunning the same mxnode upgrade command is the recovery procedure. Every per-node step is idempotent, so steps that already ran become no-ops the second time.

Audit log

Every upgrade attempt appends a MigrationEntry to state.toml’s migrations.entries[]:
[[migrations.entries]]
at = "2026-04-26T18:37:04Z"
to_binary = "v1.11.5"
strategy = "rolling"
trigger = "cli"
result = "ok"           # or "partial", "rolled-back"
duration_secs = 142
nodes_done = [0, 1, 2, 3]
nodes_failed = []

Dry run

mxnode upgrade --binary-tag v1.11.5 --dry-run
Resolves tags, builds the plan, prints what would run, then exits without touching anything.