Chain ID:orbinum_testnet
Block Height:—
RPC Status:Checking...
Node Version:—

Installation

Step-by-step installation guide for Orbinum.

Produces blocks in the permissioned testnet validator set. The RPC stays private; only P2P is public.

Nothing you type is stored by us. Values stay in this browser tab only (sessionStorage) - they survive a reload and are gone when you close the tab. A Check button sends just the values that check needs to our server, which uses them once and keeps nothing.

Before you start

CPU4 dedicated vCPU or bare metalRecommended: 8 cores
Memory8 GBRecommended: 16 GB
Disk200 GB NVMeRecommended: 500 GB NVMe
NetworkStatic public IPv4
OSUbuntu 24.04
  • A crypto-friendly provider that allows PoS validation in writing - Hetzner and Contabo are not accepted
  • Ideally a region the validator set doesn't cover yet - the application asks for provider and region
  • An Orbinum account with a little test ORB from the faucet, to register your keys

Shared or burstable vCPUs aren't enough: blocks with shielded transactions carry Groth16 proofs checked during block execution, and a throttled CPU misses its slot. Ubuntu 24.04 is the only OS the official guides are tested on. State import peaks around 5-6 GB RAM - add swap under 16 GB.

bash
nproc && free -h && df -h / && lsb_release -ds

Prepare the server

1Install Docker

Orbinum ships the node as a ready-made image, so there is nothing to compile - Docker Engine and the Compose plugin are all the server needs. This adds Docker's official apt repository (Ubuntu's own docker.io package lags behind) and lets your user run docker without sudo, which every later step assumes.

Install Docker Engine + Compose

bash
sudo apt update && sudo apt install -y ca-certificates curl git jq
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker

Run docker without sudo

bash
sudo usermod -aG docker $USER
newgrp docker
docker --version && docker compose version
Expected output
Docker version …, build …
Docker Compose version v…

If sudo apt update ends with E: or GPG errors, stop - nothing after it will work. The "gpgv required for verification" message is misleading; find the real cause with sudo apt -o Debug::Acquire::gpgv=1 update 2>&1 | grep -iE 'denied|error' | head. Seeing cannot create /dev/null: Permission denied? Fix it with sudo rm -f /dev/null && sudo mknod -m 666 /dev/null c 1 3.

If a later docker compose pull fails with "denied", the server has an old GitHub login stored - run docker logout ghcr.io and pull again. The Orbinum image is public and needs no login.

2Open the P2P port

Other validators and nodes connect to you on the P2P port - it is the only port a validator needs open. SSH is allowed first so turning the firewall on can't lock you out.

Other nodes dial you here, so it must be reachable. Change it only if 30333 is taken.

bash
sudo ufw allow 22/tcp
sudo ufw allow 30333/tcp comment 'orbinum p2p'
sudo ufw --force enable
sudo ufw status
Expected output
Status: active
22/tcp               ALLOW       Anywhere
30333/tcp            ALLOW       Anywhere      # orbinum p2p

Docker publishes container ports through its own iptables rules, which bypass ufw - so ufw is NOT what keeps the validator's RPC private; RPC_BIND=127.0.0.1 in .env is. That RPC runs with unsafe methods: anyone who reaches it can read or replace your session keys. Never set RPC_BIND to 0.0.0.0 or a public IP.

SSH on a custom port? Allow that port instead of 22.

Run the node

3Download node-deploy

The official deploy repo holds a Docker Compose stack per role and the testnet chain spec (genesis and boot nodes). You work from its testnet/validator folder from here on.

bash
git clone https://github.com/orbinum/node-deploy.git $HOME/node-deploy
cd $HOME/node-deploy/testnet/validator
[ -f .env ] || cp .env.example .env

Already cloned it for another role? Skip the clone and run git -C $HOME/node-deploy pull instead. An .env you already filled is never overwritten.

4Configure your node

All settings live in .env. Fill in the fields and the command writes them for you, generates the node key (your node's P2P identity - only on the first run, so it is safe to run again) and prints the result to check.

Shown on telemetry and in your application - pick something people recognise.

Only where Docker publishes the RPC on this server (127.0.0.1). The node itself listens on 9944 inside the container, and the commands in this guide go through docker exec, so they always use 9944. Change this only if another service on the server already uses port 9944.

Fetches the latest finalized state instead of replaying every block - about 5 minutes to the chain head on a test run (September 2026, ~560 MiB of state). Blocks before the sync point are kept as headers only - fine for producing blocks, not for serving history. Only applies to an empty data volume.

bash
cd $HOME/node-deploy/testnet/validator
sed -i "s|^VALIDATOR_NAME=.*|VALIDATOR_NAME=<your-validator-name>|" .env
grep -q '^VALIDATOR_NODE_KEY=.' .env || sed -i "s|^VALIDATOR_NODE_KEY=.*|VALIDATOR_NODE_KEY=$(openssl rand -hex 32)|" .env
sed -i "s|^SYNC_MODE=.*|SYNC_MODE=--sync warp|" .env
sed -i "s|^P2P_PORT=.*|P2P_PORT=30333|" .env
sed -i "s|^RPC_PORT=.*|RPC_PORT=9944|" .env
chmod 600 .env
grep -E '^(VALIDATOR_NAME|SYNC_MODE|P2P_PORT|RPC_PORT|RPC_BIND)=' .env
Expected output
VALIDATOR_NAME=<your-validator-name>
SYNC_MODE=--sync warp
P2P_PORT=30333
RPC_PORT=9944
RPC_BIND=127.0.0.1

Back up .env. The node key is your node's peer ID - keep it when you move servers, and never run two nodes with the same key.

5Start the node

Pulls the image and starts two containers: the validator, and Watchtower, which checks for a new testnet image every 5 minutes and restarts the node on it - node updates are automatic.

Start

bash
cd $HOME/node-deploy/testnet/validator
docker compose pull
docker compose up -d

Follow the logs (Ctrl+C stops following, not the node)

bash
cd $HOME/node-deploy/testnet/validator && docker compose logs -f --tail 50 orbinum-validator
Expected output
Warp sync is complete, continuing with state sync.
⚙️  State sync, Downloading state, 69%, 388.11 Mib (8 peers), best: #0 …
     <- the % can sit still while the Mib keeps rising - that is progress
⚙️  State sync, Importing state, 69%, 560.62 Mib (8 peers), best: #0 …
     <- then nothing moves for a few minutes: the state is being written to disk
State sync is complete, continuing with block sync.
🏆 Imported #997485 (0x8e26…355d → 0xbcd2…59d0)   <- at the chain head
⏩ Block history, #58176 (8 peers), best: #997486 …
     <- old block headers backfill in the background; the node already works

At startup the node benchmarks the server and may log The hardware does not meet the minimal requirements ... for role 'Authority'. It is a warning, not an error - the node keeps running. Look at which check failed: the targets are about 1000 MiB/s for BLAKE2-256 (CPU), 950 MiB/s sequential and 420 MiB/s random disk writes. A disk well below that risks missed slots once you are in the validator set. A single Block import error: Incomplete block import pipeline around the switch from warp to state sync is harmless as long as the log keeps moving.

Changed .env later? Apply it with docker compose up -d --force-recreate - a plain restart keeps the old settings, because a container's command is fixed when it is created.

6Wait for the sync

Session keys can only be generated on a synced node. The first command shows whether it is still syncing, the second how far it still has to go. Your node should also appear on telemetry under <your-validator-name> within a minute.

Health

bash
docker exec orbinum-validator curl -sS -H 'Content-Type: application/json' -d '{"id":1,"jsonrpc":"2.0","method":"system_health","params":[]}' http://localhost:9944 | jq

Progress

bash
docker exec orbinum-validator curl -sS -H 'Content-Type: application/json' -d '{"id":1,"jsonrpc":"2.0","method":"system_syncState","params":[]}' http://localhost:9944 | jq
Expected output
"isSyncing": false,
"peers": 8,
"shouldHavePeers": true

peers stays at 0? The server can't reach the network - check that outbound traffic is allowed and the P2P port is open.

Become a validator

7Create and fund your account

A validator is registered from a normal Orbinum account. Create one in Talisman, SubWallet or the Polkadot.js extension - the address starts with 5 - and enter it below: its public key is read straight from the address. Claim test ORB from the faucet now too; you need it in step 9, where registering the keys is a signed transaction that pays a fee.

Checked in your browser, including the address checksum - a mistyped character is caught. It is not looked up on-chain, so make sure it is the account you control.

Worked out from your address in the browser - the next step uses it. No copy-paste needed.

Optional: cross-check on the node

bash
docker exec orbinum-validator orbinum-node key inspect <your-5…-address>
Expected output
Public Key URI `<your-5…-address>` is account:
  Network ID/Version: substrate
  Public key (hex):   <account-public-key-hex>   <- same as above
  Account ID:         <account-public-key-hex>
  SS58 Address:       <your-5…-address>
Has the faucet paid out?
Fill in the fields above first.

8Generate session keys

Asks the node to create its Aura (block production) and GRANDPA (finality) keys inside its own keystore, and to sign a proof that they belong to your account - the public key from the previous step is already filled into the command. The private keys never leave the server; only the public half goes on-chain. Run it once, then paste keys and proof from the output below.

bash
docker exec orbinum-validator curl -sS -H 'Content-Type: application/json' -d '{"id":1,"jsonrpc":"2.0","method":"author_rotateKeysWithOwner","params":["<account-public-key-hex>"]}' http://localhost:9944 | jq .result
Expected output
{
  "keys": "0x…",    <- 128 hex characters
  "proof": "0x…"
}
Paste from the output

Only the format is checked here. Copy it exactly from this server's output.

Only the format is checked here. It must come from the same run as keys.

Run this on the validator server, and only once. Every run generates a new pair and the keys and proof you saved become stale - rotate after registering and you must submit session.setKeys again with the new pair, or the node stops authoring at the next session.

No proof in the result? The node is still on an older runtime - wait until isSyncing is false and run it again.

9Register the keys on-chain

Submit session.setKeys from the same account whose public key you used. First run the check below on the server - it confirms the node holds the keys you pasted, so a wrong paste is caught before you pay for a transaction. Then in Polkadot.js Apps open Developer → Extrinsics, select that account, choose session → setKeys(keys, proof), copy the values below in and sign.

keys
Appears once keys is filled in
proof
Appears once proof is filled in
aura
Only if Polkadot.js splits keys: first half
Appears once keys is filled in
grandpa
Second half
Appears once keys is filled in

Before signing: the node holds these keys

bash
docker exec orbinum-validator curl -sS -H 'Content-Type: application/json' -d '{"id":1,"jsonrpc":"2.0","method":"author_hasSessionKeys","params":["<keys>"]}' http://localhost:9944 | jq .result
Expected output
true

Session.InvalidProof means the proof doesn't match the signing account - sign with the exact account whose public key you passed in the previous step.

false? The keys you pasted aren't in this node's keystore - paste them again from the previous step's output on this server. The Cheatsheet's "Check Aura and GRANDPA Separately" shows which half is missing.

10Verify

Two things must be true before you apply, both checked from our server with the buttons below: the chain has your keys registered for your account (the same keys the node holds, checked in the previous step - if the chain points to keys the node doesn't hold, you miss your blocks), and other nodes can reach the node's P2P port.

Run curl -4 ifconfig.me on the server if you don't know it.

On-chain: your account points to these keys (session.nextKeys)
Fill in the fields above first.
P2P port reachable from the internet
Fill in the fields above first.

The P2P check connects from our server and waits for the libp2p handshake, so a pass means the node itself answered - not just an open port. Prefer your own machine? nc -vz <your-server-ip> 30333 from anywhere outside the server.

11Apply to the validator set

The testnet validator set is permissioned - up to 32 validators, no bonding. It is a human review, not a scored form: no SLA and no guaranteed slot, and a short honest email reads better than a long one. The team confirms your node is synced on telemetry before approving. Once added, the node starts producing blocks after two session rotations (about 2 hours).

Who is being added - a company page, a GitHub org or a personal handle. Also the email subject.

Networks you already validate or run. "First validator" is a fine answer.

Both are selection factors - the team spreads validators across providers and regions.

So the team can reach you when your node misbehaves.

Optional - how you would notice an outage before they do.

text
To: contact@orbinum.net
Subject: Testnet validator application - <operator name / website>

- SS58 address: <your-5…-address>
- Operator: <operator name / website>
- Experience: <networks you already validate>
- Provider / region: <provider, region>
- Contact: <Discord or Telegram handle>
- Telemetry node name: <your-validator-name>
- Monitoring: -

Once you're in, telemetry shows a ✓ next to your node in the authority set - that's what the validator's telemetry level 1 is for.

Values you type are kept in this tab only.

Contact Us

Questions about staking, delegation, or running a validator with us? Reach out directly or use the form.

Kynraze
Kynraze
Validator operator

Questions about delegating, commission, or a specific chain? Email us or send a message through the form, and we'll get back to you.