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
| Requirement | Specification |
|---|---|
| OS | Ubuntu 22.04 LTS or later (Debian-based recommended) |
| CPU | 4+ cores (8 recommended) |
| RAM | 16 GB minimum (32 GB recommended) |
| Storage | 500 GB NVMe SSD (1 TB for archive mode) |
| Network | 100+ Mbps, static IP or DNS recommended |
| Ports | 26656 (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 versionOption 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-nodeConfiguration
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.tomlKey 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"State Sync (Recommended)
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-nodeSystemd Service (Recommended)
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
EOFEnable and start:
sudo systemctl daemon-reload
sudo systemctl enable gx-node
sudo systemctl start gx-nodeCheck status:
sudo systemctl status gx-node
sudo journalctl -u gx-node -f --no-hostnameVerifying Sync Status
Check Current Height
curl -s http://localhost:4001/v1/heightCompare with the public API:
curl -s https://api.gx.exchange/v1/heightCheck 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 4000Maintenance
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
}
EOFUpgrading
# 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-nodeStorage 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
| Issue | Cause | Resolution |
|---|---|---|
| Node not syncing | No peers connected | Verify port 26656 is open and seed nodes are reachable |
| Sync stalled | Peer connection issues | Restart the node; check persistent_peers configuration |
| High memory usage | Large state during sync | Increase RAM or enable state sync |
| RPC connection refused | Listening on localhost only | Change listen_addr to 0.0.0.0 if remote access is needed |
| Disk full | Archive mode with insufficient storage | Switch to pruned mode or expand disk |
| Slow sync from genesis | Expected behavior | Use state sync instead of syncing from block 0 |
Health Monitoring
Set up alerts on these conditions:
| Condition | Alert Threshold |
|---|---|
| Sync lag | > 10 blocks behind chain tip |
| Peer count | < 3 connected peers |
| Disk usage | > 80% capacity |
| Process status | Node 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