For DevelopersNodesNon-Validating Node

Non-Validating Node Setup

This guide walks through setting up a non-validating GX Chain node from scratch. A non-validating node replicates the full chain state and serves API requests locally.

Prerequisites

RequirementSpecification
OSUbuntu 22.04 LTS or later (Debian-based recommended)
CPU4+ cores (8 recommended)
RAM16 GB minimum (32 GB recommended)
Storage500 GB NVMe SSD (1 TB for archive mode)
Network100+ Mbps, static IP or DNS recommended
Ports26656 (P2P) must be reachable for peer connections

Installation

Option 1: Pre-built Binary

# Create a dedicated user
sudo useradd -m -s /bin/bash gxnode
sudo su - gxnode
 
# Download the latest release
RELEASE_URL="https://releases.gx.exchange/gx-node/latest"
curl -L "${RELEASE_URL}/gx-node-linux-amd64" -o ~/gx-node
chmod +x ~/gx-node
 
# Verify
~/gx-node version

Option 2: Build from Source

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
 
# Clone and build
git clone https://github.com/GX-EXCHANGE/gx-node.git
cd gx-node
cargo build --release
 
# Binary is at target/release/gx-node
cp target/release/gx-node ~/gx-node

Configuration

Initialize the Node

# Initialize data directory and download genesis
~/gx-node init \
  --network mainnet \
  --data-dir /data/gx-node \
  --moniker "my-gx-node"

This creates:

  • /data/gx-node/config.toml — node configuration
  • /data/gx-node/genesis.json — chain genesis state
  • /data/gx-node/data/ — blockchain data directory

Edit Configuration

nano /data/gx-node/config.toml

Key settings to review:

[network]
chain_id = 42069
moniker = "my-gx-node"
 
# Seed nodes for peer discovery
seeds = [
  "seed1.gx.exchange:26656",
  "seed2.gx.exchange:26656",
  "seed3.gx.exchange:26656",
]
 
# Persistent peers (optional, for stable connections)
persistent_peers = []
 
[rpc]
listen_addr = "127.0.0.1:3001"    # EVM JSON-RPC
max_connections = 100
cors_allowed_origins = ["*"]       # Restrict in production
 
[api]
listen_addr = "127.0.0.1:4001"    # REST API
cors_allowed_origins = ["*"]
 
[websocket]
listen_addr = "127.0.0.1:4000"    # WebSocket
max_connections = 1000
 
[p2p]
listen_addr = "0.0.0.0:26656"     # Must be publicly reachable
max_peers = 50
 
[storage]
data_dir = "/data/gx-node/data"
pruning = "none"                   # "none" for archive, "default" for pruned
 
[logging]
level = "info"
format = "json"
output = "/var/log/gx-node/node.log"

Instead of syncing from genesis (which can take days), use state sync to start from a recent snapshot:

[state_sync]
enabled = true
trust_height = 5000000
trust_hash = "0xTrustHash..."
rpc_servers = ["https://rpc1.gx.exchange:26657", "https://rpc2.gx.exchange:26657"]

Get the current trust height and hash:

curl -s https://rpc1.gx.exchange:26657/commit | \
  jq '{height: .result.signed_header.header.height, hash: .result.signed_header.commit.block_id.hash}'

Running the Node

Direct Start

~/gx-node start --data-dir /data/gx-node

Create a systemd service for automatic startup and restart:

sudo tee /etc/systemd/system/gx-node.service > /dev/null << 'EOF'
[Unit]
Description=GX Chain Non-Validating Node
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
User=gxnode
Group=gxnode
ExecStart=/home/gxnode/gx-node start --data-dir /data/gx-node
Restart=always
RestartSec=5
LimitNOFILE=65536
 
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=gx-node
 
[Install]
WantedBy=multi-user.target
EOF

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable gx-node
sudo systemctl start gx-node

Check status:

sudo systemctl status gx-node
sudo journalctl -u gx-node -f --no-hostname

Verifying Sync Status

Check Current Height

curl -s http://localhost:4001/v1/height

Compare with the public API:

curl -s https://api.gx.exchange/v1/height

Check Peer Connections

curl -s http://localhost:26657/net_info | jq '.result.n_peers'

Monitor Sync Progress

# Watch block height in real time
watch -n 1 'curl -s http://localhost:4001/v1/height'

The node is fully synced when the local height matches (or is within 1-2 blocks of) the public API height.

Firewall Configuration

# Allow P2P connections (required for syncing)
sudo ufw allow 26656/tcp
 
# Allow local API access (restrict to localhost or your IP)
# Do NOT expose these ports publicly without authentication
sudo ufw allow from 127.0.0.1 to any port 3001
sudo ufw allow from 127.0.0.1 to any port 4001
sudo ufw allow from 127.0.0.1 to any port 4000

Maintenance

Log Rotation

sudo tee /etc/logrotate.d/gx-node > /dev/null << 'EOF'
/var/log/gx-node/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    missingok
    copytruncate
}
EOF

Upgrading

# Stop the node
sudo systemctl stop gx-node
 
# Download new binary
curl -L https://releases.gx.exchange/gx-node/latest/gx-node-linux-amd64 -o ~/gx-node
chmod +x ~/gx-node
 
# Verify version
~/gx-node version
 
# Start the node
sudo systemctl start gx-node

Storage Management

Monitor disk usage:

du -sh /data/gx-node/data/

If using pruned mode, old blocks are automatically removed. Archive nodes require ongoing storage expansion.

Troubleshooting

IssueCauseResolution
Node not syncingNo peers connectedVerify port 26656 is open and seed nodes are reachable
Sync stalledPeer connection issuesRestart the node; check persistent_peers configuration
High memory usageLarge state during syncIncrease RAM or enable state sync
RPC connection refusedListening on localhost onlyChange listen_addr to 0.0.0.0 if remote access is needed
Disk fullArchive mode with insufficient storageSwitch to pruned mode or expand disk
Slow sync from genesisExpected behaviorUse state sync instead of syncing from block 0

Health Monitoring

Set up alerts on these conditions:

ConditionAlert Threshold
Sync lag> 10 blocks behind chain tip
Peer count< 3 connected peers
Disk usage> 80% capacity
Process statusNode process not running
Memory usage> 90% of available RAM
# Example health check script
#!/bin/bash
LOCAL_HEIGHT=$(curl -s http://localhost:4001/v1/height | jq -r '.height')
PUBLIC_HEIGHT=$(curl -s https://api.gx.exchange/v1/height | jq -r '.height')
LAG=$((PUBLIC_HEIGHT - LOCAL_HEIGHT))
 
if [ "$LAG" -gt 10 ]; then
  echo "ALERT: Node is $LAG blocks behind"
fi