Skip to main content

Node Flags

node-deploy sets these for you in each role's Compose file. This page is for reading what is already there, or diverging from it deliberately.


Common flags​

FlagDescriptionDefault
--chainChain specificationdev
--base-pathData directoryplatform-specific
--nameNode name, shown in telemetryrandom
--portP2P port30333
--rpc-portRPC port — serves both HTTP and WebSocket9944
--validatorAuthor blocksfalse
--state-pruningHow much state to keep (archive, or a block count)256
--blocks-pruningHow many block bodies to keep256
--syncSync mode: full, fast, fast-unsafe, warpfull
--databaseDatabase backend; paritydb is experimentalRocksDB
--prometheus-portMetrics port9615
There is no --ws-port

Substrate unified HTTP and WebSocket onto one port. --pruning still parses, but only as an alias for --state-pruning — it does not control block-body pruning, so use the canonical pair.


What each role sets​

FlagPublic RPCValidator
--validator—✅
--experimental-rpc-endpoint✅ two, methods=safe (see below)—
--rpc-external—optional, empty by default
--rpc-max-connections3500 HTTP + 1500 WSdefault
--state-pruning archive✅— (default pruning)
--blocks-pruning archive✅—
SYNC_MODE (--sync)❌ cannot warpoptional, empty by default
--prometheus-external✅✅
--in-peers / --out-peers64 / 16default
--no-mdns✅✅

Bootnodes come from the chain spec, so no role passes --bootnodes.

--sync warp and archive nodes are incompatible

An archive node exits at startup with Warp sync doesn't work for archive nodes and, under restart: unless-stopped, crash-loops. Only the validator roles expose SYNC_MODE, and only they can use it.

On a validator it also applies just once: the node ignores it as soon as it holds finalized state, logging Can't use warp sync mode with a partially synced database. Reverting to full sync mode. And because the validator is not an archive node, what warp skips is backfilled headers only — no block bodies before the sync point, permanently.


RPC methods​

Unsafe RPC methods — author_rotateKeys, author_insertKey, author_removeExtrinsic, system_addReservedPeer, offchain_* and the like — change the node itself, so a public endpoint must not serve them.

orbinum-node 0.4.0 and earlier force --rpc-methods Unsafe on every role, so --rpc-methods Safe has no effect there. 0.5.0 and later leave the choice to the operator. ISMP queries (ismp_*) and grandpa_proveFinality work under Safe, so the Hyperbridge relayer does not need unsafe methods.

The public RPC therefore declares its endpoints with --experimental-rpc-endpoint, which carries its own method set and is not affected by the forced flag:

--experimental-rpc-endpoint "listen-addr=0.0.0.0:9944,methods=safe,max-request-size=150,max-response-size=150,max-connections=3500"
--experimental-rpc-endpoint "listen-addr=127.0.0.1:9945,methods=safe,max-request-size=150,max-response-size=150,max-connections=1500,rate-limit=1200"
EndpointServesLimits
9944 (RPC_BIND)Caddy's HTTPS upstream, and hosts on the private network (the Hyperbridge relayer)3500 connections
9945 (loopback)Caddy's WSS upstream1500 connections, 1200 calls/min per socket

An unsafe call on either answers RPC call is unsafe to be called externally.

Do not add cors= to an endpoint

Setting cors on an --experimental-rpc-endpoint also turns on the node's Host filter, which admits only localhost. Every request Caddy forwards carries the public domain as its Host and is refused with Provided Host header is not whitelisted. Caddy sets the CORS headers itself.

An endpoint also does not inherit the 150 MiB request and response limits the binary sets for --rpc-port; without max-request-size / max-response-size it falls back to 15 MiB, which truncates large GRANDPA proofs.

The validator keeps the classic flags and stays on loopback, so its unsafe methods are unreachable from outside the host. See Ports & Endpoints for where each role binds.


Peering​

VariableEffect
PUBLIC_ADDRAdvertise a specific address to peers
RESERVED_NODES is not additive

A non-empty value activates --reserved-only: the node refuses every peer not on the list — the bootnodes included — so a public node silently ends up with zero peers. Leave it empty unless you are running a private network or a validator behind sentries.

Validators behind sentries

A validator behind its own sentry nodes lists every sentry in RESERVED_NODES, so it peers with, and takes transactions from, them alone. A peer that sends shielded-pool spends with invalid proofs loses too little reputation to get banned, so a validator open to every peer keeps verifying whatever that peer sends; behind sentries, only the sentries reach it.


Logging​

ORB=ghcr.io/orbinum/node:testnet-latest

# raise verbosity
docker run --rm -e RUST_LOG=debug $ORB --dev --tmp

# one module only
docker run --rm -e RUST_LOG=pallet_shielded_pool=trace $ORB --dev --tmp

Chain spec​

All three testnet roles mount the same file read-only and point --chain at it:

../chainspec/testnet-spec.json  →  /chain-specs/testnet-spec.json

The spec is generated in the node repo and copied into node-deploy, which only consumes it. It carries the bootnodes.

For a custom spec, export one, edit it, convert it to raw and run it:

docker run --rm $ORB build-spec --chain local > custom-spec.json
docker run --rm -v "$PWD:/specs" $ORB build-spec --chain /specs/custom-spec.json --raw > custom-spec-raw.json
docker run --rm -v "$PWD:/specs" $ORB --chain /specs/custom-spec-raw.json