🔌 Installation
0G-Chain Complete Node and Validator Setup Guide
Part 1: Node Installation
➡️ Install Required Packages
sudo apt update && sudo apt upgrade -y
sudo apt install curl git wget htop tmux build-essential jq make lz4 gcc unzip -y
➡️ Install Go
cd $HOME
VER="1.23.4"
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=$PATH:/usr/local/go/bin:~/go/bin" >> ~/.bash_profile
source $HOME/.bash_profile
[ ! -d ~/go/bin ] && mkdir -p ~/go/bin
➡️ Download and Install Node Files
cd $HOME
wget https://github.com/0glabs/0gchain-NG/releases/download/v2.0.3/galileo-v2.0.3.tar.gz && tar -xvzf galileo-v2.0.3.tar.gz
rm -rf galileo-v2.0.3.tar.gz
mv $HOME/galileo-v2.0.3 $HOME/galileo-used
➡️ Set Permissions
mv $HOME/galileo-used/bin/geth $HOME/go/bin/geth
mv $HOME/galileo-used/bin/0gchaind $HOME/go/bin/0gchaind
chmod +x $HOME/go/bin/*
➡️ Set Environment Variables
Info
OG_PORT
to any available base port. All services will use this as a prefix. echo "export OG_MONIKER=your-moniker-name" >> $HOME/.bash_profile
echo "export OG_PORT=56" >> $HOME/.bash_profile
source $HOME/.bash_profile
➡️ Initialize Node
mkdir -p $HOME/.0gchaind
cp -r $HOME/galileo-used/0g-home $HOME/.0gchaind
geth init --datadir $HOME/.0gchaind/0g-home/geth-home $HOME/galileo-used/genesis.json
0gchaind init $OG_MONIKER --home $HOME/.0gchaind/tmp
mv $HOME/.0gchaind/tmp/data/priv_validator_state.json $HOME/.0gchaind/0g-home/0gchaind-home/data/
mv $HOME/.0gchaind/tmp/config/node_key.json $HOME/.0gchaind/0g-home/0gchaind-home/config/
mv $HOME/.0gchaind/tmp/config/priv_validator_key.json $HOME/.0gchaind/0g-home/0gchaind-home/config/
rm -rf $HOME/.0gchaind/tmp
➡️ Configure Ports and Settings
sed -i "s|^moniker *=.*|moniker = \"${OG_MONIKER}\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
geth-config.toml
sed -i "s/HTTPPort = .*/HTTPPort = ${OG_PORT}545/" $HOME/galileo-used/geth-config.toml
sed -i "s/WSPort = .*/WSPort = ${OG_PORT}546/" $HOME/galileo-used/geth-config.toml
sed -i "s/AuthPort = .*/AuthPort = ${OG_PORT}551/" $HOME/galileo-used/geth-config.toml
sed -i "s|ListenAddr = .*|ListenAddr = \":${OG_PORT}303\"|" $HOME/galileo-used/geth-config.toml
sed -i "s|^# *Port = .*|# Port = ${OG_PORT}901|" $HOME/galileo-used/geth-config.toml
sed -i "s|^# *InfluxDBEndpoint = .*|# InfluxDBEndpoint = \"http://localhost:${OG_PORT}086\"|" $HOME/galileo-used/geth-config.toml
sed -i 's/^WSHost = "0\.0\.0\.0"/WSHost = "127.0.0.1"/' $HOME/galileo-used/geth-config.toml
sed -i 's/^AuthAddr = "0\.0\.0\.0"/AuthAddr = "127.0.0.1"/' $HOME/galileo-used/geth-config.toml
Do not use these codes if you are going to use rpc as public
sed -i 's/^HTTPHost = "0\.0\.0\.0"/HTTPHost = "127.0.0.1"/' $HOME/galileo-used/geth-config.toml
client.toml
sed -i "s|node = .*|node = \"tcp://localhost:${OG_PORT}657\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/client.toml
config.toml
sed -i "s|laddr = \"tcp://0.0.0.0:26656\"|laddr = \"tcp://0.0.0.0:${OG_PORT}656\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
sed -i "s|laddr = \"tcp://127.0.0.1:26657\"|laddr = \"tcp://127.0.0.1:${OG_PORT}657\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
sed -i "s|^proxy_app = .*|proxy_app = \"tcp://127.0.0.1:${OG_PORT}658\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
sed -i "s|^pprof_laddr = .*|pprof_laddr = \"127.0.0.1:${OG_PORT}060\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
sed -i "s|prometheus_listen_addr = \".*\"|prometheus_listen_addr = \"127.0.0.1:${OG_PORT}660\"|" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
➡️ Configure Pruning and Indexer
sed -i 's/beacon-kit/chaincfg/g' $HOME/.0gchaind/0g-home/0gchaind-home/config/app.toml
sed -i -e "s/^pruning *=.*/pruning = \"custom\"/" $HOME/.0gchaind/0g-home/0gchaind-home/config/app.toml
sed -i -e "s/^pruning-keep-recent *=.*/pruning-keep-recent = \"100\"/" $HOME/.0gchaind/0g-home/0gchaind-home/config/app.toml
sed -i -e "s/^pruning-interval *=.*/pruning-interval = \"19\"/" $HOME/.0gchaind/0g-home/0gchaind-home/config/app.toml
sed -i -e "s/^indexer *=.*/indexer = \"null\"/" $HOME/.0gchaind/0g-home/0gchaind-home/config/config.toml
➡️ Create Symlink and Download Addrbook
ln -sf $HOME/.0gchaind/0g-home/0gchaind-home/config/client.toml $HOME/.0gchaind/config/client.toml
Info
Updated every 6 hours.
curl https://files.mictonode.com/0g/addrbook/addrbook.json -o $HOME/.0gchaind/0g-home/0gchaind-home/config/addrbook.json
➡️ Set Environment Variables for 0gchaind Service
Note:
BLOCK_NUM
: The maximum block number range per call when syncing restaking events. Default is 1. Adjust this according to the limitations of your RPC service.
echo "export ETH_RPC_URL=your-holesky-rpc" >> $HOME/.bash_profile
echo "export BLOCK_NUM=your-holesky-rpc" >> $HOME/.bash_profile
source $HOME/.bash_profile
➡️ Create Service Files
Note: If you are not setting up a validator node
--chaincfg.restaking.enabled \\
--chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \\
--chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \\
you can delete these parts.
0gchaind Service:
sudo tee /etc/systemd/system/0gchaind.service > /dev/null <<EOF
[Unit]
Description=0gchaind Node Service
After=network-online.target
[Service]
User=$USER
ExecStart=$HOME/go/bin/0gchaind start \\
--chaincfg.chain-spec devnet \\
--chaincfg.kzg.trusted-setup-path=$HOME/galileo-used/kzg-trusted-setup.json \\
--chaincfg.engine.jwt-secret-path=$HOME/galileo-used/jwt-secret.hex \\
--chaincfg.kzg.implementation=crate-crypto/go-kzg-4844 \\
--chaincfg.block-store-service.enabled \\
--chaincfg.node-api.enabled \\
--chaincfg.node-api.logging \\
--chaincfg.engine.rpc-dial-url=http://localhost:${OG_PORT}551 \\
--chaincfg.node-api.address 127.0.0.1:${OG_PORT}500 \\
--chaincfg.restaking.enabled \\
--chaincfg.restaking.symbiotic-rpc-dial-url ${ETH_RPC_URL} \\
--chaincfg.restaking.symbiotic-get-logs-block-range ${BLOCK_NUM} \\
--home=$HOME/.0gchaind/0g-home/0gchaind-home \\
--p2p.seeds=85a9b9a1b7fa0969704db2bc37f7c100855a75d9@8.218.88.60:26656 \\
--p2p.external_address $(curl -s http://ipv4.icanhazip.com):${OG_PORT}656
WorkingDirectory=$HOME/galileo-used
Restart=always
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
Geth Service:
sudo tee /etc/systemd/system/geth.service > /dev/null <<EOF
[Unit]
Description=0g Geth Node Service
After=network-online.target
[Service]
User=$USER
ExecStart=$HOME/go/bin/geth \\
--config $HOME/galileo-used/geth-config.toml \\
--datadir $HOME/.0gchaind/0g-home/geth-home \\
--networkid 16601 \\
--bootnodes enode://de7b86d8ac452b1413983049c20eafa2ea0851a3219c2cc12649b971c1677bd83fe24c5331e078471e52a94d95e8cde84cb9d866574fec957124e57ac6056699@8.218.88.60:30303
Restart=always
WorkingDirectory=$HOME/galileo-used
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
➡️ Download Snapshot
Install Required
sudo apt update && sudo apt install aria2 -y
Check Snapshot Height
echo "0G Snapshot Height: $(curl -s https://files.mictonode.com/0g/snapshot/block-height.txt)"
cp $HOME/.0gchaind/0g-home/0gchaind-home/data/priv_validator_state.json $HOME/.0gchaind/0g-home/0gchaind-home/priv_validator_state.json.backup
rm -rf $HOME/.0gchaind/0g-home/0gchaind-home/data
rm -rf $HOME/.0gchaind/0g-home/geth-home/geth/chaindata
mkdir -p $HOME/.0gchaind/0g-home/geth-home/geth
SNAPSHOT_URL="https://files.mictonode.com/0g/snapshot/"
LATEST_COSMOS=$(curl -s $SNAPSHOT_URL | grep -oP '0g_\d{8}-\d{4}_\d+_cosmos\.tar\.lz4' | sort | tail -n 1)
LATEST_GETH=$(curl -s $SNAPSHOT_URL | grep -oP '0g_\d{8}-\d{4}_\d+_geth\.tar\.lz4' | sort | tail -n 1)
if [ -n "$LATEST_COSMOS" ] && [ -n "$LATEST_GETH" ]; then
COSMOS_URL="${SNAPSHOT_URL}${LATEST_COSMOS}"
GETH_URL="${SNAPSHOT_URL}${LATEST_GETH}"
echo "Downloading Cosmos snapshot: $LATEST_COSMOS"
aria2c -x 16 -s 16 -k 1M --continue=true --dir=/tmp --out="$LATEST_COSMOS" "$COSMOS_URL"
lz4 -dc /tmp/"$LATEST_COSMOS" | tar -xf - -C $HOME/.0gchaind/0g-home/0gchaind-home
rm -f /tmp/"$LATEST_COSMOS"
echo "Downloading Geth snapshot: $LATEST_GETH"
aria2c -x 16 -s 16 -k 1M --continue=true --dir=/tmp --out="$LATEST_GETH" "$GETH_URL"
lz4 -dc /tmp/"$LATEST_GETH" | tar -xf - -C $HOME/.0gchaind/0g-home/geth-home/geth
rm -f /tmp/"$LATEST_GETH"
mv $HOME/.0gchaind/0g-home/0gchaind-home/priv_validator_state.json.backup $HOME/.0gchaind/0g-home/0gchaind-home/data/priv_validator_state.json
else
echo "Snapshot not found."
fi
➡️ Start Services
sudo systemctl daemon-reload
sudo systemctl enable geth.service
sudo systemctl start geth.service
sudo systemctl enable 0gchaind.service
sudo systemctl start 0gchaind.service
➡️ Block Sync Status Check
local_height=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:${OG_PORT}545 | jq -r '.result' | xargs printf "%d\n");
network_height=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' https://evmrpc-testnet.0g.ai | jq -r '.result' | xargs printf "%d\n");
blocks_left=$((network_height - local_height));
echo "Local EVM height: $local_height";
echo "Network EVM height: $network_height";
echo "Remaining blocks: $blocks_left"
- Node height – the current block height of your node
- Network height – the latest block height on the network
- Remaining blocks – number of blocks left for your node to fully sync
➡️ Check Logs
sudo journalctl -u 0gchaind -u geth -f
sudo journalctl -u 0gchaind -f -o cat
sudo journalctl -u geth -f -o cat
➡️ Faucet
Part 2: Validator Creation
Important: Your node must be fully synced before creating validator!
➡️ Install Foundry
curl -L https://foundry.paradigm.xyz | bash
source ~/.bashrc
foundryup
➡️ Set Your Private Key
You need an EVM wallet private key (from MetaMask, Trust Wallet, etc.) with at least 32 OG tokens:
export PRIVATE_KEY=0xYOUR_PRIVATE_KEY_HERE
➡️ Step 1: Generate Validator Keys
0gchaind deposit validator-keys \
--home ~/.0gchaind/0g-home/0gchaind-home \
--chaincfg.chain-spec=devnet
Save the pubkey from output.
➡️ Step 2: Get Validator Contract Address
Replace YOUR_PUBKEY
with the pubkey from step 1:
cast call \
0xea224dBB52F57752044c0C86aD50930091F561B9 \
"computeValidatorAddress(bytes)(address)" \
YOUR_PUBKEY \
--rpc-url https://evmrpc-testnet.0g.ai
Save the address from output.
➡️ Step 3: Create Signature
Replace YOUR_VALIDATOR_ADDRESS
with address from step 2:
0gchaind deposit create-validator \
YOUR_VALIDATOR_ADDRESS \
32000000000 \
~/.0gchaind/0g-home/0gchaind-home/config/genesis.json \
--home ~/.0gchaind/0g-home/0gchaind-home \
--chaincfg.chain-spec=devnet
Save both pubkey and signature from output.
➡️ Step 4: Create Validator
Replace the values with your data:
cast send 0xea224dBB52F57752044c0C86aD50930091F561B9 \
"createAndInitializeValidatorIfNecessary((string,string,string,string,string),uint32,uint96,bytes,bytes)" \
'("YourValidatorName","keybase-id","https://website.com","email@domain.com","Validator description")' \
50000 1 \
YOUR_PUBKEY \
YOUR_SIGNATURE \
--gas-limit 1000000 \
--gas-price 50000000000 \
--value 32000000000000000000 \
--rpc-url https://evmrpc-testnet.0g.ai \
--private-key YOUR_PRIVATE_KEY
➡️ Verification
Check if validator was created successfully:
cast call 0xea224dBB52F57752044c0C86aD50930091F561B9 \
"getValidator(bytes)(address)" \
YOUR_PUBKEY \
--rpc-url https://evmrpc-testnet.0g.ai
Useful Commands
Check wallet balance:
cast balance YOUR_WALLET_ADDRESS --rpc-url https://evmrpc-testnet.0g.ai
Add more stake:
cast send YOUR_VALIDATOR_CONTRACT_ADDRESS \
"delegate(address)" \
YOUR_WALLET_ADDRESS \
--value 1ether \
--private-key YOUR_PRIVATE_KEY \
--rpc-url https://evmrpc-testnet.0g.ai
Update validator info:
cast send YOUR_VALIDATOR_CONTRACT_ADDRESS \
"updateDescription((string,string,string,string,string))" \
'("NewName","new-keybase","https://newsite.com","new@email.com","New description")' \
--rpc-url https://evmrpc-testnet.0g.ai \
--private-key YOUR_PRIVATE_KEY
➡️ Clear Node !!!
Warning
Make sure you have backed up your wallet key
& priv_validator_key.json
cd $HOME
sudo systemctl stop 0gchaind geth
sudo systemctl disable 0gchaind geth
sudo rm /etc/systemd/system/0gchaind.service
sudo rm /etc/systemd/system/geth.service
sudo systemctl daemon-reload
sudo rm -f $(which 0gchaind)
sudo rm -f $(which geth)
sudo rm -rf $HOME/.0gchaind
sudo rm -rf $HOME/galileo-used