Upgrade a Node
Upgrade native or Docker nodes safely with manual and agentic procedures, rollback, and validator identity gates.
Upgrade a ROKO node
First compare the September 10 network update and network manifest with the artifact you intend to install. The managed correction 764f8c1, public September 8 nightly, and historical v1.1.0 package are different revisions. Do not downgrade to match an older guide or promote an unqualified build by changing a download pointer.
Use an explicitly approved immutable release path or architecture-specific image digest. The live configured testnet uses runtime spec 286 (mainnet), which is independent of a package's name. Verify the selected artifact's compatibility with the exact genesis and on-chain runtime; a testnet label alone neither establishes nor disproves that compatibility.
The runtime was activated at finalized block 839462 on 2026-08-28. A node binary replacement does not call System.setCode. Query runtime version at a finalized block rather than inferring activation from the executable version.
Upgrade validators one at a time. Full, archive, sentry, and observer nodes may be upgraded in parallel only while independent RPC, boot, and time-mesh capacity remains online.
This procedure replaces software only. It must not replace the chain spec, base path, node identity, session keys, temporal key, or service credentials.
Preflight
Record the following before stopping anything:
- release tag, source revision, and artifact SHA-256 or image digest;
- installed unit and current executable or image digest;
- genesis hash, finalized head, peer count, sync state, and node role;
- authority index and PTP² mesh state for a validator; and
- the expected stash and all seven public session keys from the approved enrollment manifest for a validator.
A healthy unit, correct genesis, peers, and isSyncing: false prove that a host is a synchronized peer. They do not prove that it owns an active authority slot. Confirm finality is advancing and the remaining authorities can retain quorum. Stop if the network is already degraded.
The examples use roko-node.service, /usr/local/bin/roko-node, and loopback RPC on port 9944. Discover the real values from the installed unit instead of guessing them.
: "${ROKO_RELEASE:?Set the approved immutable release ID}"
: "${ROKO_SOURCE_REVISION:?Set the approved full source revision}"
ROKO_SERVICE=roko-node.service
ROKO_RPC=http://127.0.0.1:9944
systemctl show "$ROKO_SERVICE" -p FragmentPath -p ExecStart -p ActiveState
chronyc tracking
chronyc sources -v
curl --fail --silent --show-error "$ROKO_RPC" \
-H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"system_health","params":[]}'
curl --fail --silent --show-error "$ROKO_RPC" \
-H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"chain_getFinalizedHead","params":[]}'
curl --fail --silent --show-error "$ROKO_RPC" \
-H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"temporal_getMeshState","params":[]}'
Manual native-binary upgrade
Download the architecture-matched bundle and checksum manifest into a new private staging directory:
ROKO_RELEASE_BASE="https://downloads.roko.network/releases/${ROKO_RELEASE}"
case "$(uname -m)" in
x86_64) ROKO_ARCH=amd64 ;;
aarch64|arm64) ROKO_ARCH=arm64 ;;
*) echo "Unsupported architecture" >&2; exit 1 ;;
esac
: "${ROKO_BUNDLE:?Set the compatible architecture-matched archive from release metadata}"
mkdir -m 0700 "roko-upgrade-${ROKO_RELEASE}"
cd "roko-upgrade-${ROKO_RELEASE}"
curl --fail --location --remote-name "${ROKO_RELEASE_BASE}/${ROKO_BUNDLE}"
curl --fail --location --remote-name "${ROKO_RELEASE_BASE}/SHA256SUMS"
curl --fail --location --remote-name "${ROKO_RELEASE_BASE}/BUILD-METADATA.json"
sha256sum --check --ignore-missing SHA256SUMS
jq -e --arg release "$ROKO_RELEASE" --arg source "$ROKO_SOURCE_REVISION" \
'.release_id == $release and .source_revision == $source' \
BUILD-METADATA.json
tar -xzf "$ROKO_BUNDLE"
./roko-node --version
Require an OK checksum and the expected revision before touching the service. Stage the binary on the same filesystem and preserve the previous executable:
sudo install -o root -g root -m 0755 roko-node \
/usr/local/bin/roko-node.new
sudo systemctl stop "$ROKO_SERVICE"
sudo cp --preserve=mode,ownership,timestamps \
/usr/local/bin/roko-node \
"/usr/local/bin/roko-node.before-${ROKO_RELEASE}"
sudo mv /usr/local/bin/roko-node.new /usr/local/bin/roko-node
sudo systemctl start "$ROKO_SERVICE"
Do not delete the previous binary until the observation window passes.
Manual Docker upgrade
Use an architecture-specific immutable tag only to discover the image, then pin the resolved digest in the service environment:
: "${ROKO_RELEASE:?Set the approved immutable release ID}"
: "${ROKO_SOURCE_REVISION:?Set the approved full source revision}"
case "$(uname -m)" in
x86_64) ROKO_ARCH=amd64 ;;
aarch64|arm64) ROKO_ARCH=arm64 ;;
*) echo "Unsupported architecture" >&2; exit 1 ;;
esac
: "${ROKO_CANDIDATE:?Set the approved compatible architecture-specific image reference}"
docker pull "$ROKO_CANDIDATE"
ROKO_IMAGE_DIGEST="$(docker image inspect "$ROKO_CANDIDATE" \
--format '{{index .RepoDigests 0}}')"
ROKO_IMAGE_REVISION="$(docker image inspect "$ROKO_CANDIDATE" \
--format '{{index .Config.Labels "org.opencontainers.image.revision"}}')"
case "$ROKO_IMAGE_DIGEST" in
*@sha256:*) ;;
*) echo "Image did not resolve to a registry digest" >&2; exit 1 ;;
esac
test "$ROKO_IMAGE_REVISION" = "$ROKO_SOURCE_REVISION"
printf 'digest=%s\
revision=%s\
' \
"$ROKO_IMAGE_DIGEST" "$ROKO_IMAGE_REVISION"
docker run --rm "$ROKO_IMAGE_DIGEST" --version
Record the digest, preserve the previous environment file, set ROKO_IMAGE to the digest rather than the tag, and restart only the node unit:
sudo cp -a /etc/roko/node-image.env \
"/etc/roko/node-image.env.before-${ROKO_RELEASE}"
printf 'ROKO_IMAGE=%s\
' "$ROKO_IMAGE_DIGEST" |
sudo tee /etc/roko/node-image.env >/dev/null
sudo systemctl restart "$ROKO_SERVICE"
Post-upgrade acceptance
Inspect the unit and recent logs, then repeat the preflight RPC checks:
sudo systemctl status "$ROKO_SERVICE" --no-pager
sudo journalctl -u "$ROKO_SERVICE" --since '-10 minutes' --no-pager
Wait for the expected version and genesis, connected peers and completed sync before starting the finality measurement window. RPC availability alone is not a successful startup. Retain failed checks and the verified rollback result.
Require all of the following before moving to another validator:
- expected version and revision are running;
- genesis is unchanged and
isSyncingbecomes false; - best and finalized heads advance across multiple observations and match an independent trusted node at a common finalized height;
- peers return to the expected range;
- Chrony is healthy and
temporal_getMeshStatereturnsConvergedafter warm-up; - the expected authority role and non-null time quality are present, with a fresh finalized authorship proof after restart for an elected validator; and
- there are no repeated BABE, GRANDPA, database, time-source, OOM, or restart errors.
AUTHORED and readyToAuthor can retain historical evidence during a stall. Check proof height and observation time. For an unelected candidate or a full node, validate its intended role instead of requiring active authorship.
Acceptance for an elected validator is an identity join. At the same finalized head, prove:
- host keystore public filenames match the approved seven-key manifest;
session.nextKeys(expected_stash)matches that manifest byte for byte;- the expected stash is in
session.validators, not onlystaking.invulnerables,staking.validators, orsession.queuedKeys; - active BABE, GRANDPA, and temporal keys map to that host; and
- the host authors blocks and has the correct non-null producer authority index and
temporal_getValidatorTimeQualityresult.
Record configured, queued, and active membership separately. Session changes are protocol-timed; do not declare success while only the configured or queued set matches.
Rollback
Restore only the saved executable or prior image digest. Do not roll back chain data after an upgraded node writes to it unless release notes explicitly state that the database format is backward compatible. Repeat every acceptance check after rollback and record the reason.
Agentic upgrade contract
An automation agent may perform this upgrade only after the operator supplies or approves the target hosts, release tag, immutable artifact, and rollout order. Give the agent this bounded contract:
Upgrade my ROKO node to the explicitly approved immutable release and source
revision using the public ROKO upgrade guide.
Discover the actual unit, executable or image, chain spec, base path, node
identity, role, and loopback RPC before changing anything. Capture preflight
evidence without printing secrets. Verify the immutable checksum or image
digest and embedded source revision. Preserve the chain spec, data, node
identity, keystore, temporal key, credentials, and a tested rollback target.
For validators, upgrade one host at a time. Stop if finality, peers, clock,
storage, memory, or another validator is unhealthy. After restart, wait for
sync, advancing finality, correct active authority identity, authorship, and
PTP² convergence before continuing. Compare the complete intended set with
session.validators and session.queuedKeys; validator count or
staking.invulnerables alone is insufficient. A synced host absent from the
active session may be a candidate; record that role without claiming active
authorship.
Stop on the first failed gate. Do not rotate keys, change chain spec, delete
data, move a release tag, submit governance, or widen network exposure. Produce
a value-free receipt with host, old and new revisions, artifact digest,
timestamps, health results, and rollback disposition.
The agent must ask before any action outside that contract.