Set Up a ZIGChain Node
TL;DR: Run ZIGChain node setup with scripts or manual steps on Linux or Mac. Sync with state sync or snapshots. Confirm health with the local RPC status API.
Overview
ZIGChain node setup walks you through installing zigchaind and preparing $HOME/.zigchain. You download genesis, set peers, enable state sync, set gas, start the node, and optionally add a system service.
This guide gives step-by-step instructions for a ZIGChain full node on x86 Linux or Mac. It covers config, system management, and why each step matters.
Key Concepts
- zigchaind: CLI binary used to initialize, configure, start, and operate a ZIGChain full node.
- State sync: Bootstrap method that trusts a recent block from an RPC endpoint instead of replaying the full chain history.
- Genesis file: Network starting configuration downloaded from the ZIGChain networks repository into
~/.zigchain/config/. - Persistent peers: Comma-separated peer addresses in
config.tomlthat keep your node connected to the network. - Minimum gas price:
minimum-gas-pricesvalue inapp.toml(for example0.0025uzig) that the node enforces before accepting transactions. - Catching up: Field in the RPC
sync_inforesponse;falseindicates the node has finished synchronizing.
State sync and chain snapshots are different ways to catch up quickly. For nodes that serve explorers, dApps, or other RPC clients that require the full historical transaction log, state sync is not appropriate — these workloads still need a fully synced node with the entire block history. If state sync is unavailable or fails, use Snapshots as an alternative bootstrap method.
Automated Setup Scripts
You can use our automated setup scripts to run ZIGChain node setup quickly on your machine, or install it manually by following the steps below.
These scripts cover the core ZIGChain node setup tasks so you can join your chosen network without editing every file by hand.
Supported platforms
- Linux (x86)
- Mac (Apple Silicon)
- Mac (Intel)
- Linux
- Mac ARM
- Mac AMD
curl -O https://raw.githubusercontent.com/ZIGChain/docs/main/scripts/start-linux.sh
chmod +x start-linux.sh
./start-linux.sh
curl -O https://raw.githubusercontent.com/ZIGChain/docs/main/scripts/start-macos.sh
chmod +x start-macos.sh
./start-macos.sh
curl -O https://raw.githubusercontent.com/ZIGChain/docs/main/scripts/start-macos.sh
chmod +x start-macos.sh
./start-macos.sh
The scripts will guide you through:
- Installing the
zigchaindbinary - Setting up your node for your chosen network
- Configuring state sync and peer connections
- Setting up your node with the correct chain-id and genesis file
When the script finishes, continue with Start the Node below.
Manual ZIGChain Node Setup
The following steps guide you through manual ZIGChain node setup on an x86 Linux machine or on a Mac (Apple Silicon or Intel).
Prerequisites
Plan ZIGChain node setup on hardware that can keep up with your target network load. Open the ports below before you install the binary.
Recommended Hardware Requirements
- Core Processor: 8-core (4 physical core), x86_64 architecture
- Memory: 32 GB RAM
- Storage: 1 TB SSD
- Network: Stable internet connection
Open Network Ports
Ensure the following ports are open:
2665626657
Install zigchaind
Ensure that zigchain CLI or zigchaind is installed on your system. If not, follow the Quick Start Guide.
Initialize the Node
The init step of ZIGChain node setup creates local config under $HOME/.zigchain. Run it once per fresh data directory.
To set up the local configuration files needed for the node to run, initialize the ZIGChain node.
This process creates essential files and directories inside $HOME/.zigchain.
To create the necessary configuration files, run:
zigchaind init <node_name> --chain-id <chain_id>
- Mainnet
- Testnet
- Local
zigchaind init mynode --chain-id zigchain-1
zigchaind init mynode --chain-id zig-test-2
zigchaind init mynode --chain-id zigchain-1
If you get the error: genesis.json file already exists.
You can remove the zigchain data rm -rf $HOME/.zigchain and run it again.
After initialization, the following directory structure is created:
~/.zigchain
├── config
│ ├── app.toml
│ ├── client.toml
│ ├── config.toml
│ ├── genesis.json
│ ├── node_key.json
│ └── priv_validator_key.json
└── data
└── priv_validator_state.json
Download the Genesis File
Your ZIGChain node setup needs the correct genesis file for the network you join. ZIGChain maintains a public repository with genesis, seeds, and RPC nodes.
Download the latest genesis file for your network:
- Mainnet
- Testnet
wget https://raw.githubusercontent.com/ZIGChain/networks/refs/heads/main/zigchain-1/genesis.json -O ~/.zigchain/config/genesis.json
wget https://raw.githubusercontent.com/ZIGChain/networks/refs/heads/main/zig-test-2/genesis.json -O ~/.zigchain/config/genesis.json
Configure the Node
During ZIGChain node setup, you tune config.toml for network connectivity and sync options.
Modify config.toml for network connectivity.
vim ~/.zigchain/config/config.toml
Key configuration parameters:
| Setting | Value |
|---|---|
moniker | Your node's name, (e.g., mynode) |
log_level | info |
seeds | See next section |
You can adjust multiple settings as needed. For more details, refer to the CometBFT Configuration.
Set Up State Sync
To sync up your node with the network, enable the State Sync service in the config.toml.
For the complete, platform-specific walkthrough and troubleshooting tips, refer to State Sync Configuration.
- Mainnet
- Testnet
SNAP_RPC="https://public-zigchain-rpc.numia.xyz:443"
SEED_NODES="https://raw.githubusercontent.com/ZIGChain/networks/main/zigchain-1/seed-nodes.txt"
SNAP_RPC="https://public-zigchain-testnet-rpc.numia.xyz:443"
SEED_NODES="https://raw.githubusercontent.com/ZIGChain/networks/main/zig-test-2/seed-nodes.txt"
- Linux
- Mac ARM
- Mac AMD
LATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height)
BLOCK_HEIGHT=$((LATEST_HEIGHT - 5000))
TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)
sed -i.bak -E \
"s|^(enable[[:space:]]*=[[:space:]]*).*$|\1true| ; \
s|^(rpc_servers[[:space:]]*=[[:space:]]*).*$|\1\"$SNAP_RPC,$SNAP_RPC\"| ; \
s|^(trust_height[[:space:]]*=[[:space:]]*).*$|\1$BLOCK_HEIGHT| ; \
s|^(trust_hash[[:space:]]*=[[:space:]]*).*$|\1\"$TRUST_HASH\"|" \
"$HOME/.zigchain/config/config.toml"
LATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \
BLOCK_HEIGHT=$((LATEST_HEIGHT - 5000)); \
TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)
sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \
s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$SNAP_RPC,$SNAP_RPC\"| ; \
s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \
s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"|" "$HOME/.zigchain/config/config.toml"
LATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \
BLOCK_HEIGHT=$((LATEST_HEIGHT - 5000)); \
TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)
sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \
s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$SNAP_RPC,$SNAP_RPC\"| ; \
s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \
s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"|" "$HOME/.zigchain/config/config.toml"
If State Sync Fails
State sync depends on the RPC endpoint still having the trusted block available. If the node fails to sync or the trust window has expired, you can bootstrap from a snapshot instead. See Snapshots for available options.
Set Up Peers
To connect your node to others in the network, update persistent peers in the config.toml.
persistent_peers = "<peer_id>@<peer_address>:26656"
- Mainnet
- Testnet
persistent_peers = "[email protected]:26656,[email protected]:26656"
persistent_peers = "dc9725eac15e7887a4b8deb4eddfbf4cf641778f@testnet-seed0.zigchain.com:26656"
Get the full list of peers from ZIGChain Networks and add them to the configuration file directly:
- Linux
- Mac ARM
- Mac AMD
SEED_FILE=REPLACE-ME-WITH-SEED-FILE-PATH
wget $SEED_NODES -O $SEED_FILE
SEEDS=$(paste -sd, "$SEED_FILE")
sed -i -E "s|^(persistent_peers[[:space:]]*=[[:space:]]*).*|\1\"$SEEDS\"|" "$HOME/.zigchain/config/config.toml"
SEED_FILE=REPLACE-ME-WITH-SEED-FILE-PATH
wget $SEED_NODES -O $SEED_FILE
SEEDS=$(paste -sd, "$SEED_FILE")
sed -i '' -E "s|^(persistent_peers[[:space:]]*=[[:space:]]*).*|\1\"$SEEDS\"|" "$HOME/.zigchain/config/config.toml"
SEED_FILE=REPLACE-ME-WITH-SEED-FILE-PATH
wget $SEED_NODES -O $SEED_FILE
SEEDS=$(paste -sd, "$SEED_FILE")
sed -i '' -E "s|^(persistent_peers[[:space:]]*=[[:space:]]*).*|\1\"$SEEDS\"|" "$HOME/.zigchain/config/config.toml"
Set Up Minimum Gas Price
Set gas during ZIGChain node setup so your node accepts network transactions. Modify app.toml to set minimum gas price to 0.0025uzig.
vim ~/.zigchain/config/app.toml
Find the line containing minimum-gas-prices and update it:
minimum-gas-prices = "0.0025uzig"
Start the Node
Starting the ZIGChain node initiates synchronization with the network you configured, allowing it to connect and participate in consensus.
After ZIGChain node setup is complete in config files, zigchaind start connects your machine to the network.
To start the node, run the following command:
zigchaind start
Example Output:
5:11PM INF service start impl=Node module=server msg="Starting Node service"
5:11PM INF serve module=rpc-server msg="Starting RPC HTTP server on 127.0.0.1:26657"
Verify Node Status
The last ZIGChain node setup check confirms sync and RPC health on your host.
Check if the node is running and syncing correctly:
curl -s localhost:26657/status | grep -o '"sync_info":{[^}]*}' | sed 's/"sync_info"://' | json_pp
Example Output:
{
"catching_up": false,
"earliest_app_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"earliest_block_hash": "BBAEC1030E0F1E5CC84E7AD90DBBF833092C21E5A7877ED5D0AC53333544AE86",
"earliest_block_height": "1",
"earliest_block_time": "2025-01-29T10:00:24.662688409Z",
"latest_app_hash": "4C5CABFC67074A26CFEDAEFAE8C2CAEAF1FBD360868A00F2F5A844333ADA646C",
"latest_block_hash": "4DE43846C6CD75C962B7A962DEC81D475F68F524DCA80E076497E1DBC1D51F69",
"latest_block_height": "115789",
"latest_block_time": "2025-02-09T16:26:42.581094257Z"
}
Key fields:
latest_block_height: Shows the current block height.catching_up: Should befalsewhen the node is fully synchronized.
Setting Up System Service and Logs
Production ZIGChain node setup often runs zigchaind as a background service with rotated logs. Replace ZUSER with the username of the account running the blockchain node.
- Linux
- Mac ARM
- Mac AMD
Create Log files for zigchaind
Create log files and service file for the blockchain node.
ZUSER="zigchain"
sudo mkdir -p /var/log/zigchaind
sudo touch /var/log/zigchaind/main.log
sudo touch /var/log/zigchaind/error.log
sudo chown -R $ZUSER:$ZUSER /var/log/zigchaind
sudo touch /etc/systemd/system/zigchaind.service
Create a systemd file
Create a configuration file for the blockchain node.
ZUSER="zigchain"
sudo bash -c "cat > /etc/systemd/system/zigchaind.service" << EOM
[Unit]
Description=zigchaind daemon
After=network-online.target
[Service]
User=$ZUSER
ExecStart=/home/$ZUSER/go/bin/zigchaind start --home=/home/$ZUSER/.zigchain
WorkingDirectory=/home/$ZUSER/go/bin
StandardOutput=file:/var/log/zigchaind/main.log
StandardError=file:/var/log/zigchaind/error.log
Restart=always
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
EOM
Starting a daemon
Start the blockchain node as a daemon:
sudo systemctl enable zigchaind.service
sudo systemctl start zigchaind.service
Other useful commands
sudo systemctl status zigchaind.service
sudo systemctl stop zigchaind.service
sudo systemctl restart zigchaind.service
sudo systemctl disable zigchaind.service
View the service logs:
tail -f /var/log/zigchaind/main.log
Activate log rotate for the logs
Install logrotate:
sudo apt install logrotate -y
Set up the logrotate configuration:
LOGROTATE_CONF="/etc/logrotate.d/zigchaind"
ZUSER="zigchain"
sudo bash -c "cat > $LOGROTATE_CONF" <<EOL
/var/log/zigchaind/*.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 $ZUSER $ZUSER
sharedscripts
postrotate
systemctl restart zigchaind.service > /dev/null 2>&1 || true
endscript
}
EOL
Test the logrotate configuration:
sudo logrotate -d $LOGROTATE_CONF
Force log rotation to ensure it works:
sudo logrotate -f $LOGROTATE_CONF
echo "Logrotate configuration for /var/log/zigchaind/ has been created and activated."
Create Log directories for zigchaind
Create log directories for the blockchain node.
ZUSER="zigchain"
sudo mkdir -p /usr/local/var/log/zigchaind
sudo touch /usr/local/var/log/zigchaind/main.log
sudo touch /usr/local/var/log/zigchaind/error.log
sudo chown -R ${ZUSER}:staff /usr/local/var/log/zigchaind
Create a LaunchDaemon plist file
Create a Launch Daemon configuration file for the blockchain node.
ZUSER="zigchain"
sudo bash -c "cat > /Library/LaunchDaemons/com.zigchain.zigchaind.plist" << EOM
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.zigchain.zigchaind</string>
<key>ProgramArguments</key>
<array>
<string>/Users/$ZUSER/go/bin/zigchaind</string>
<string>start</string>
<string>--home=/Users/$ZUSER/.zigchain</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/$ZUSER/go/bin</string>
<key>StandardOutPath</key>
<string>/usr/local/var/log/zigchaind/main.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/zigchaind/error.log</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>$ZUSER</string>
</dict>
</plist>
EOM
Starting the daemon
Load and start the blockchain node as a daemon:
sudo launchctl load /Library/LaunchDaemons/com.zigchain.zigchaind.plist
sudo launchctl start com.zigchain.zigchaind
Other useful commands
List all current jobs that contains "zigchain"
sudo launchctl list | grep zigchain
Stops the running job with the label
sudo launchctl stop com.zigchain.zigchaind
Disables the job
sudo launchctl unload /Library/LaunchDaemons/com.zigchain.zigchaind.plist
View the service logs
tail -f /usr/local/var/log/zigchaind/main.log
Set up log rotation
Install newsyslog configuration for log rotation
ZUSER="ZUSER"
sudo tee -a /etc/newsyslog.conf > /dev/null <<EOL
/usr/local/var/log/zigchaind/main.log ${ZUSER}:staff 644 7 1000 * G
/usr/local/var/log/zigchaind/error.log ${ZUSER}:staff 644 7 1000 * G
EOL
Test the newsyslog configuration
sudo newsyslog -v
echo "Log rotation for /usr/local/var/log/zigchaind/ has been configured."
Create Log directories for zigchaind
Create log directories for the blockchain node.
ZUSER="zigchain"
sudo mkdir -p /usr/local/var/log/zigchaind
sudo touch /usr/local/var/log/zigchaind/main.log
sudo touch /usr/local/var/log/zigchaind/error.log
sudo chown -R ${ZUSER}:staff /usr/local/var/log/zigchaind
Create a LaunchDaemon plist file
Create a Launch Daemon configuration file for the blockchain node.
ZUSER="zigchain"
sudo bash -c "cat > /Library/LaunchDaemons/com.zigchain.zigchaind.plist" << EOM
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.zigchain.zigchaind</string>
<key>ProgramArguments</key>
<array>
<string>/Users/$ZUSER/go/bin/zigchaind</string>
<string>start</string>
<string>--home=/Users/$ZUSER/.zigchain</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/$ZUSER/go/bin</string>
<key>StandardOutPath</key>
<string>/usr/local/var/log/zigchaind/main.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/zigchaind/error.log</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>$ZUSER</string>
</dict>
</plist>
EOM
Starting the daemon
Load and start the blockchain node as a daemon:
sudo launchctl load /Library/LaunchDaemons/com.zigchain.zigchaind.plist
sudo launchctl start com.zigchain.zigchaind
Other useful commands
List all current jobs that contains "zigchain"
sudo launchctl list | grep zigchain
Stops the running job with the label
sudo launchctl stop com.zigchain.zigchaind
Disables the job
sudo launchctl unload /Library/LaunchDaemons/com.zigchain.zigchaind.plist
View the service logs
tail -f /usr/local/var/log/zigchaind/main.log
Set up log rotation
Install newsyslog configuration for log rotation
ZUSER="ZUSER"
sudo tee -a /etc/newsyslog.conf > /dev/null <<EOL
/usr/local/var/log/zigchaind/main.log ${ZUSER}:staff 644 7 1000 * G
/usr/local/var/log/zigchaind/error.log ${ZUSER}:staff 644 7 1000 * G
EOL
Test the newsyslog configuration
sudo newsyslog -v
echo "Log rotation for /usr/local/var/log/zigchaind/ has been configured."
In production environments, it is recommended to implement a monitoring system to track logs and monitor the health of the blockchain node.
Common Questions
What should I do if genesis.json already exists during init?
If you see genesis.json file already exists., remove the existing data directory and run zigchaind init again with your chosen chain ID:
rm -rf $HOME/.zigchain
When should I use snapshots instead of state sync?
Use snapshots when state sync fails or the trust window has expired. State sync depends on the RPC endpoint still having the trusted block available. If the node will not catch up, bootstrap from a snapshot instead. See Snapshots for available options.
How do I know the node has finished syncing?
Run curl -s localhost:26657/status and inspect sync_info. When catching_up is false, the node is fully synchronized. latest_block_height shows the current block height.
Can I use state sync for an explorer or archive RPC node?
You should not rely on state sync alone for that workload. Explorers, dApps, and other RPC clients that need the full historical transaction log require a fully synced node with the entire block history. State sync does not provide that archive.