🌐 Gnoland Mainnet Full Node & Validator Setup Guide
A complete guide to running a Gnoland mainnet full node and registering as a validator
Build from source, genesis download and verification, configuration, sync, and validator registration via GovDAO — step by step.
Author: HazenNetworkSolutions
Network: Gnoland Mainnet (Chain ID: gnoland-1)
Branch: chain/mainnet
Launch: 2026-09-12T15:00:00Z
Last Updated: September 2026
Table of Contents
- Before You Start — Mainnet Differences
- Hardware Requirements
- Network Endpoints
- Step 1 — System Verification
- Step 2 — System Update and Dependencies
- Step 3 — Install Go
- Step 4 — Get the Binaries
- Step 5 — Initialize, Download Genesis and Config
- Step 6 — Configure the Node
- Step 7 — Create Systemd Service
- Step 8 — Sync Speed Note
- Step 9 — Start the Node
- Step 10 — Create a Wallet
- Step 11 — Register as a Validator
- Backups & Key Hygiene
- Useful Commands
- Firewall
- What's New Since Pearl
- Staying Updated
Before You Start — Mainnet Differences
If you have run Topaz, Sapphire or Pearl, the mechanics below will look familiar. Four things are genuinely different on gnoland-1, and each one breaks a habit from the testnet line:
| Testnet habit | Mainnet reality |
|---|---|
~2.6–2.7 MB genesis built from examples/ | ~324 MB genesis (~55.8 MB gzipped) carrying the full token allocation — 3,262,481 accounts, ~1.333B GNOT |
| Grab GNOT from the faucet | No faucet. Balances come from the audited independence-day allocation (pinned at 30ec189) |
| Freely move GNOT between your own addresses | Transfers locked at genesis (Constitution §126, restricted_denoms=["ugnot"] + a 91-address exemption list); ~96% of most rows vests linearly over 24 months from launch (§132) |
| Deploy a realm whenever you want | Inert code-submission policy from block 1 — post-genesis MsgAddPackage parks until the funded gpao approvals oracle clears it; MsgRun is gated to the seeded GovDAO member |
ℹ️ Gas fees are payable from a locked or still-vesting balance — fee collection bypasses both the transfer restriction and the vesting schedule. Registering and managing a validator is therefore possible even though your allocation is locked.
⚠️ There is no reset safety net here. A double-sign on mainnet is a real, permanent slashing event — never run two nodes with the same
priv_validator_key.json.
Hardware Requirements
| Component | Minimum | Recommended |
|---|---|---|
| Operating System | Ubuntu 22.04+ | Ubuntu 24.04 |
| CPU | 4 cores | 8 cores |
| RAM | 16 GB | 32 GB |
| Disk | 250 GB SSD | 500 GB NVMe SSD |
| Network | 100 Mbps | 1 Gbps |
ℹ️ Unlike the testnets, the requirements above are driven by the genesis file itself: the raw
genesis.jsonis ~324 MB and loads 3.26M accounts atInitChain. Keep headroom for the raw download, the gunzip, and the resulting application state. Genesis balance loading is no longer quadratic in this release (#6134), but the first boot still takes materially longer than a testnet boot.
Network Endpoints
| Type | Endpoint |
|---|---|
| RPC | https://rpc.gno.land |
| Explorer (Gnoweb) | https://gno.land |
| Valopers | https://gno.land/r/gnops/valopers |
| Active Validators | https://gno.land/r/sys/validators/v0 |
| Namespaces | https://gno.land/r/sys/names |
| Seed 1 | [email protected]:26656 |
| Seed 2 | [email protected]:26656 |
| Container images | ghcr.io/gnolang/gno/gnoland:chain-mainnet |
| Official Docs | https://docs.gno.land |
| GitHub | https://github.com/gnolang/gno |
ℹ️ There is no faucet endpoint on mainnet, and no official public tx-indexer / status / Gnockpit URL announced with this release — if you need indexed data, run
gnolang/tx-indexeragainst your own node.
Step 1 — System Verification
After SSH-ing into your server, verify the system meets requirements:
lsb_release -a
uname -r
lscpu | grep -E "Model name|CPU\(s\)|Thread|Socket|Core"
free -h
df -h
Step 2 — System Update and Dependencies
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git wget htop tmux build-essential jq make lz4 gcc unzip \
screen btop iotop nethogs hdparm cmake perl automake autoconf libtool libssl-dev zstd pv
Step 3 — Install Go
Mainnet requires Go 1.25+, same line as Pearl. This step installs Go 1.25.12 and configures the PATH:
cd $HOME
VER="1.25.12"
wget "https://golang.org/dl/go$VER.linux-amd64.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go$VER.linux-amd64.tar.gz"
rm "go$VER.linux-amd64.tar.gz"
[ ! -f ~/.bash_profile ] && touch ~/.bash_profile
echo 'export PATH=/usr/local/go/bin:$HOME/go/bin:$PATH' >> ~/.bash_profile
echo 'export GNOROOT=$HOME/gno' >> ~/.bash_profile
source $HOME/.bash_profile
[ ! -d ~/go/bin ] && mkdir -p ~/go/bin
export PATH="$HOME/go/bin:$PATH"
Verify the installation:
go version
Expected output:
go version go1.25.12 linux/amd64
ℹ️ If your installed Go is older than 1.25 but at least 1.21,
GOTOOLCHAIN=auto(the default) will transparently download the pinned toolchain on the first build — but installing 1.25+ directly avoids relying on that.
ℹ️ Like Sapphire and Pearl, the
chain/mainnetrelease assets are built withCGO_ENABLED=0, so the prebuiltgnoland/gnokey/gnowebbinaries carry no newer-glibc dependency. Either path in Step 4 works.
Step 4 — Get the Binaries
You have two options: use the prebuilt release binaries, or build from source. Everything is built from the chain/mainnet branch (target commit 9c8eb132e).
Option A — Prebuilt binaries (recommended)
Download the binaries matching your OS/arch from the chain/mainnet release page (gnoland, gnokey, gnoweb, gno — linux_amd64, linux_arm64, darwin_amd64, darwin_arm64), then verify against the release's CHECKSUMS.txt:
cd $HOME
wget https://github.com/gnolang/gno/releases/download/chain/mainnet/gno_linux_amd64
wget https://github.com/gnolang/gno/releases/download/chain/mainnet/gnoland_linux_amd64
wget https://github.com/gnolang/gno/releases/download/chain/mainnet/gnokey_linux_amd64
wget https://github.com/gnolang/gno/releases/download/chain/mainnet/gnoweb_linux_amd64
wget https://github.com/gnolang/gno/releases/download/chain/mainnet/CHECKSUMS.txt
sha256sum -c CHECKSUMS.txt --ignore-missing
sudo install -m 0755 gno_linux_amd64 /usr/local/bin/gno
sudo install -m 0755 gnoland_linux_amd64 /usr/local/bin/gnoland
sudo install -m 0755 gnokey_linux_amd64 /usr/local/bin/gnokey
sudo install -m 0755 gnoweb_linux_amd64 /usr/local/bin/gnoweb
Reference checksums from the release (verify, don't trust this file):
CHECKSUMS.txt a5fa1e7ffd238d0364b0c82f94ae23f5884bfc19729954cb369a447ddae6e442
gnoland_linux_amd64 c7cf41abaf056058bb41c9f26f89686b7cb09b206160bff0a3e6c27755d091c5
gnokey_linux_amd64 f6230d9fcd5426643784937583fadf61beb08ccab420fc97ec3ebfeb571e6b98
The rest of this guide runs its gnoland/gnokey commands from a $HOME/gno working directory (that's where Step 5 downloads genesis.json and where the systemd service's WorkingDirectory/GNOROOT point). Option B gets this directory for free from git clone; on the prebuilt-binary path you need to create it yourself:
mkdir -p $HOME/gno
Option B — Build from source
Clone the official gno repository and checkout the mainnet branch:
cd $HOME
git clone https://github.com/gnolang/gno.git
cd gno
git checkout chain/mainnet
Build and install all binaries:
make -C gno.land install.gnoland install.gnokey
make install
make -C contribs/gnogenesis install
Copy binaries to system path and set permissions:
for bin in gno gnokey gnodev gnoland gnogenesis gnoweb; do
sudo cp /root/go/bin/$bin /usr/local/bin/
sudo chmod +x /usr/local/bin/$bin
done
Option C — Docker
docker pull ghcr.io/gnolang/gno/gnoland:chain-mainnet
# or build it yourself from the checked-out branch:
docker build --target gnoland -t gnoland:mainnet .
Verify the installation (any option)
gno version
gnoland version
Expected output (or similar):
gnoland version: chain/mainnet
Step 5 — Initialize, Download Genesis and Config
Run a quick start to generate the default data directory structure, then stop with Ctrl+C:
cd $HOME/gno
gnoland start --lazy
ℹ️ Wait until you see the node start printing output, then press
Ctrl+Cto stop it.
Remove the default data and genesis to prepare for a clean setup:
rm -rf gnoland-data/ genesis.json
Download the official mainnet genesis. Prefer the gzipped asset — the raw file is ~324 MB:
cd $HOME/gno
wget -O genesis.json.gz \
https://github.com/gnolang/gno/releases/download/chain/mainnet/genesis.json.gz
gunzip genesis.json.gz
Or download the raw file directly:
wget -O genesis.json \
https://github.com/gnolang/gno/releases/download/chain/mainnet/genesis.json
Verify the genesis checksum — the hash must match exactly:
shasum -a 256 genesis.json
Expected output:
ea22691003130eae3ba975b7d16460706b5d75ce6c04ae82c0c4faeab7de91f0 genesis.json
⚠️ If the checksum does not match, do not continue. Re-download the genesis file. On mainnet this check is the difference between joining the real chain and joining nothing.
ℹ️ Gzipped-asset checksum, if you want to verify before decompressing:
32a0fef8db3c71fa8360dee39a0149ee961be115ba81363a15f854e4aad446c9.
ℹ️ To regenerate the genesis yourself rather than downloading it, follow
misc/deployments/mainnet.gno.land/README.mdon thechain/mainnetbranch. The allocation is sha256-pinned and reconciled against the shipped genesis at build time, and a build-time guard refuses any §132 schedule that is not fully locked at genesis.
Initialize node secrets and config:
gnoland secrets init
gnoland config init
Step 6 — Configure the Node
Set your moniker (replace with your own node name):
MONIKER="YOUR_MONIKER"
Apply all required configuration settings:
cd $HOME/gno
gnoland config set moniker "$MONIKER"
gnoland config set application.prune_strategy syncable
gnoland config set consensus.timeout_commit 3s
gnoland config set consensus.peer_gossip_sleep_duration 10ms
gnoland config set p2p.flush_throttle_timeout 10ms
gnoland config set p2p.pex true
gnoland config set p2p.max_num_outbound_peers 40
gnoland config set mempool.size 10000
gnoland config set telemetry.metrics_enabled false
gnoland config set p2p.laddr "tcp://0.0.0.0:26656"
gnoland config set rpc.laddr "tcp://127.0.0.1:26657"
gnoland config set p2p.external_address "YOUR-SERVER-IP:26656"
gnoland config set p2p.persistent_peers \
"[email protected]:26656,[email protected]:26656"
ℹ️ Replace
YOUR-SERVER-IPwith your actual server's public IP address.
ℹ️ The first five settings above are listed by mainnet's own
VALIDATOR.mdas chain-wide and must match exactly:p2p.persistent_peers,application.prune_strategy,consensus.timeout_commit,consensus.peer_gossip_sleep_duration,p2p.flush_throttle_timeout.mempool.sizeandp2p.max_num_outbound_peersare advised;moniker,p2p.external_addressandp2p.pexare per node (pex=truefor a standalone node).
ℹ️ Running a sentry setup instead of a standalone node? See the Sentry-node architecture section of the
gnolandREADME — worth considering on mainnet, where your consensus key is a permanent liability.
Step 7 — Create Systemd Service
Create the systemd service file to run the node as a managed background process:
sudo tee /etc/systemd/system/gnoland.service > /dev/null << EOF
[Unit]
Description=Gnoland gnoland-1 Node
After=network-online.target
Wants=network-online.target
[Service]
User=root
WorkingDirectory=/root/gno
Environment=GNOROOT=/root/gno
Environment=HOME=/root
ExecStart=$(which gnoland) start \\
--chainid gnoland-1 \\
--genesis /root/gno/genesis.json \\
--skip-genesis-sig-verification
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
StandardOutput=journal
StandardError=journal
SyslogIdentifier=gnoland
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable gnoland
⚠️
--skip-genesis-sig-verificationis required — some genesis transactions carry placeholder or intentionally-invalidated signatures (e.g. thenames.Enablecall runs with a patched caller), and the node panics on startup without this flag.
Step 8 — Sync Speed Note
This is where mainnet deviates most from the testnet guides. The testnets booted a ~2.7 MB genesis in seconds; gnoland-1 loads a ~324 MB genesis with 3.26M accounts, so the first InitChain takes minutes, not seconds — the node will look silent while it works. Do not restart it in a panic.
After genesis is loaded, block sync is ordinary and fast: the chain launched 2026-09-12T15:00:00Z, so the history you need to replay is short at the time of writing and grows from there.
If you want to watch progress instead of waiting blind, see the sync-status command in Step 9 or Useful Commands.
Step 9 — Start the Node
Start the gnoland service:
sudo systemctl restart gnoland
Follow the live logs to confirm the node is running:
sudo journalctl -u gnoland -f --no-hostname -o cat
Verify the service status:
sudo systemctl status gnoland --no-pager
Expected output:
● gnoland.service - Gnoland gnoland-1 Node
Active: active (running) since ...
Check sync status:
curl -s http://localhost:26657/status | jq .result.sync_info
Expected output when fully synced:
{
"latest_block_height": "XXXXXX",
"catching_up": false
}
⚠️ Wait until
catching_upisfalsebefore proceeding to validator registration.
Step 10 — Create a Wallet
Create a new wallet:
gnokey add wallet
⚠️ CRITICAL: You will be shown a mnemonic phrase. Save it offline immediately. Without it, you cannot recover your wallet. On mainnet this phrase controls real GNOT — do not paste it into any file, chat, or note that syncs to a cloud.
To recover an existing wallet from mnemonic:
gnokey add wallet --recover
List your wallets and get your g1... address:
gnokey list
Expected output:
* wallet (local) - addr: g1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx pub: gpub1...
Verify your balance:
gnokey query \
-remote "https://rpc.gno.land" \
auth/accounts/YOUR-G1-ADDRESS
⚠️ There is no faucet on mainnet, and transfers are locked at launch (Constitution §126). A freshly created address will hold nothing and you cannot top it up from another address you own unless the sender is on the 91-address exemption list. If you are joining after genesis, your operator address must be an address that already holds GNOT in the genesis allocation.
ℹ️ Founding validators are funded at genesis: both the signing address and the operator address hold 1,000 GNOT from the §122 Validator Services Treasury, which covers registration and ordinary management transactions. Gas fees are payable out of a locked/vesting balance, so the §132 schedule does not block node operation.
Step 11 — Register as a Validator
⚠️ Gnoland uses a GovDAO-based validator registration system. Registration is done by calling a realm (smart contract). Becoming active in the validator set requires a GovDAO governance proposal to pass — registration alone only lists you as a candidate.
ℹ️ Mainnet launches with 4 founding validators — Gnocore, OnBloc, Samourai Crew, Berty — one each at power 60. At 4 × 60, one validator going dark is ¼ of the power, below the ⅓ halt boundary (Pearl sat exactly on that boundary with 3 × 60). Governance starts with aeddi as sole GovDAO T1 member, seeded with 9 invitation points; six further confirmed members join post-genesis by proposal.
Get your Validator Public Key
Run from the /root/gno directory:
cd /root/gno && gnoland secrets get validator_key
Expected output:
{
"address": "g1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"pub_key": "gpub1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
⚠️ Only the
pub_keyis used for registration. Theaddresshere is the consensus key address — do not use it as the operator address. Use your funded wallet address fromgnokey listinstead.
Submit Validator Registration
Replace all placeholder values before running. The registration must be signed by your operator key — the gnokey account whose g1... address you pass as the operator address; the realm rejects the call if the signer doesn't control that address:
gnokey maketx call \
--pkgpath gno.land/r/gnops/valopers \
--func Register \
--args "MONIKER" \
--args "DESCRIPTION" \
--args "cloud|on-prem|data-center" \
--args "OPERATOR_ADDRESS" \
--args "VAL_PUBKEY" \
--gas-fee 1000000ugnot \
--gas-wanted 50000000 \
--chainid gnoland-1 \
--remote https://rpc.gno.land \
--broadcast \
WALLETNAME
| Placeholder | Description |
|---|---|
MONIKER | Your validator display name |
DESCRIPTION | Short description of your validator |
cloud|on-prem|data-center | Your infrastructure category |
OPERATOR_ADDRESS | Your wallet g1... address from gnokey list — must hold GNOT |
VAL_PUBKEY | pub_key from cd /root/gno && gnoland secrets get validator_key |
WALLETNAME | Key name from gnokey list |
ℹ️ After a successful transaction you can view your profile at:
https://gno.land/r/gnops/valopersRegistering only lists you as a candidate — a GovDAO member must then create and pass a proposal (via
r/sys/validators/v0, note the/v0path, not the testnets'/v3) to add you to the active validator set. Once that proposal executes, your node joins the valset.
Update Description (Optional)
Description limit is 2048 characters. To update after registration:
gnokey maketx call \
--pkgpath gno.land/r/gnops/valopers \
--func UpdateDescription \
--args "YOUR-G1-OPERATOR-ADDRESS" \
--args "YOUR-NEW-DESCRIPTION" \
--gas-fee 1000000ugnot \
--gas-wanted 50000000 \
--chainid gnoland-1 \
--remote https://rpc.gno.land \
--broadcast \
WALLETNAME
Backups & Key Hygiene
On the testnets a lost key meant re-registering. Here it means losing a funded operator identity, and a duplicated consensus key means double-signing. Back up off-server, right after Step 5:
# from your local machine
scp -r root@YOUR-SERVER-IP:/root/gno/gnoland-data/secrets ./backup/secrets
scp root@YOUR-SERVER-IP:/root/gno/gnoland-data/config/config.toml ./backup/config/config.toml
What each file is:
| File | Meaning |
|---|---|
priv_validator_key.json | Your consensus signing key. Losing it = losing the validator. Copying it to a second running node = double-sign. |
priv_validator_state.json | Last signed height/round. Restoring a stale copy onto a running node can cause a double-sign. |
node_key.json | P2P identity only — regenerable, but your peer ID changes. |
config.toml | Your node configuration (Step 6). |
Rules: encrypt the backup at rest, never commit it to a repository, keep exactly one node holding the validator key at any time, and never restore priv_validator_state.json from an older snapshot onto a node that has signed since.
Useful Commands
Service Management
sudo systemctl start gnoland
sudo systemctl stop gnoland
sudo systemctl restart gnoland
sudo systemctl status gnoland
Logs & Sync
# Live logs
sudo journalctl -u gnoland -f --no-hostname -o cat
# Logs from last hour
sudo journalctl -u gnoland --since "1 hour ago"
# Sync status
curl -s http://localhost:26657/status | jq .result.sync_info
# Connected peers
curl -s http://localhost:26657/net_info | jq .result.n_peers
# Consensus state (who is prevoting/precommitting right now)
curl -s http://localhost:26657/dump_consensus_state | jq '.result.round_state.height_vote_set'
Node Info
ℹ️ Run secrets commands from
/root/gnodirectory:
cd /root/gno && gnoland secrets get node_id
cd /root/gno && gnoland secrets get validator_key
cd /root/gno && gnoland secrets get
Wallet & Balance
# List wallets
gnokey list
# Check balance
gnokey query \
-remote "https://rpc.gno.land" \
auth/accounts/YOUR_ADDRESS
Send Tokens
gnokey maketx send \
-send "1000000ugnot" \
-to "RECIPIENT_ADDRESS" \
-gas-fee 1000000ugnot \
-gas-wanted 10000000 \
-broadcast \
-chainid "gnoland-1" \
-remote "https://rpc.gno.land" \
wallet
⚠️ This will fail at launch for ordinary addresses:
ugnotis a restricted denom under Constitution §126 and only the 91 exempted senders can transfer. Gas fees are unaffected.
Firewall
# P2P — must be open to the public
sudo ufw allow 26656/tcp comment "gnoland P2P"
# RPC — open only if you serve public endpoints
sudo ufw allow 26657/tcp comment "gnoland RPC"
What's New Since Pearl
Mainnet is built on chain/mainnet (commit 9c8eb132e), succeeding chain/pearl (c4c72fdd2). See the chain/mainnet release notes for the full changelog.
Breaking / consensus-relevant:
- Native gas metering, package-hash binding and authority APIs (#6171) — plus gas accounting, redeploy and peer bookkeeping fixes (#6164) and switch-case gas metering (#5217). Anything you gas-benchmarked on Pearl must be re-measured here.
p/*packages versioned under/v0and genesis-bound packages moved out of the unclaimabledemonamespace (#6162, #6159); boards2 + namereg renumbered (#6172). This is why the valset realm isr/sys/validators/v0and not/v3. Import paths from testnet code will not resolve unchanged.- Vesting is now a field on
BaseAccountrather than an account type (#6095). - Unused
MsgDisablePackageremoved (#6130).
Mainnet genesis line:
- Constitution §126 transfer lock + exemption list (#6155).
- Fee-payer ∩ vested-allocation merge — burn added to the liquid part, schedule carried verbatim (#6170).
- Inert code-submission policy armed at genesis; solo T1 with 9 invitation points (#6168); package set repathed + token standards added (#6166).
- 89 curated packages at genesis on the
/v0layout (Pearl had 85).
Node / VM:
- Genesis balance loading no longer quadratic (#6134) — necessary for a 3.26M-account genesis.
- Bank transfer events for
ugnotmovements (#6120); allowance preserved on failed grc20 self-transfer (#6138). - Bounded-parallel queries, pre-filled VM type caches, snapshot-isolated simulate (#6082).
- ABCI responses record fsynced; block stopped when its write fails (#6085).
- Range-subject stack offset fix for ASSIGN-form range (#6150).
Tooling:
- gpao (package-approvals oracle) hardening: budget debits at broadcast, startup-query retries, resolver faults treated as unavailability, parked-redeploy reporting, docker image (#6111, #6115, #6116, #6112, #6145).
- txtar harness for multi-validator clusters (#6135).
Namespaces registered at genesis: gnoswap, onbloc, moul, aeddi, aib, samcrew, howl, alongside the universal system names. r/sys/names enforcement is on from block 1.
Staying Updated
- Discord: Gnoland Discord
- GitHub: gnolang/gno
- Official Docs: docs.gno.land
- Explorer: gno.land
- Deployment folder: misc/deployments/mainnet.gno.land
Upgrade to a New Version
sudo systemctl stop gnoland
cd $HOME/gno
git fetch --all --tags
git checkout chain/NEXT_TAG
make -C gno.land install.gnoland install.gnokey
make install
make -C contribs/gnogenesis install
sudo cp /root/go/bin/gnoland /usr/local/bin/
sudo chmod +x /usr/local/bin/gnoland
sudo systemctl restart gnoland
sudo journalctl -u gnoland -f --no-hostname -o cat
⚠️ On mainnet, consensus-breaking upgrades are coordinated — typically via a GovDAO-approved
halt_height. Don't upgrade ahead of the announced height, and don't lag behind it: either way your node forks off or stalls.
About the Author
This guide was prepared by HazenNetworkSolutions.
🌐 hazennetworksolutions.com