Skip to main content

Node Setup

This guide walks through setting up a Specter full node from scratch. A full node validates all transactions and blocks, maintains a complete copy of the blockchain state, and can serve RPC queries. Validators should start here before proceeding to the Validator Guide.

Hardware Requirements

ResourceMinimumRecommended
CPU4 cores8+ cores
RAM16 GB32 GB
Storage500 GB SSD1 TB NVMe SSD
Network100 Mbps1 Gbps
OSUbuntu 22.04 LTS / macOS 13+Ubuntu 22.04 LTS

Storage requirements grow over time as the chain accumulates state. NVMe SSDs are strongly recommended for validators due to the I/O demands of CometBFT consensus and EVM state access.

Software Prerequisites

SoftwareVersionPurpose
Go1.21+Building umbralined from source
Git2.xCloning the repository
MakeGNU MakeBuild automation
jq1.6+JSON processing for scripts

Install Go

# Download and install Go 1.21+
wget https://go.dev/dl/go1.21.6.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz

# Add to PATH (add to ~/.bashrc or ~/.zshrc for persistence)
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin

# Verify
go version
# go version go1.21.6 linux/amd64

Build from Source

# Clone the repository
git clone https://github.com/specter-chain/umbraline-cosmos.git
cd umbraline-cosmos

# Build the binary
make install

# Verify installation
umbralined version

The make install command compiles the umbralined binary and places it in $GOPATH/bin.

Initialize the Node

# Set your node's moniker (human-readable name)
MONIKER="my-specter-node"

# Initialize the node
umbralined init $MONIKER --chain-id umbraline_5446-1

This creates the following directory structure at ~/.umbralined/:

~/.umbralined/
├── config/
│ ├── app.toml # Application configuration (EVM, API, gas)
│ ├── config.toml # CometBFT configuration (P2P, RPC, consensus)
│ ├── genesis.json # Genesis state (will be replaced)
│ ├── node_key.json # P2P identity key
│ └── priv_validator_key.json # Validator signing key (BACK THIS UP)
└── data/
└── priv_validator_state.json # Validator state tracking

Configure Genesis

Replace the auto-generated genesis file with the official Specter genesis:

# Download the official genesis file
curl -L https://raw.githubusercontent.com/specter-chain/network-config/main/testnet/genesis.json \
-o ~/.umbralined/config/genesis.json

# Verify the genesis hash
sha256sum ~/.umbralined/config/genesis.json
# Expected: <check official documentation for current hash>

The genesis file contains the initial chain state, including the genesis allocation of 1 billion GHOST tokens distributed across the treasury, operator, faucet, and validator accounts.

Configure Peers

Your node needs peers to discover the network. Add seed nodes and persistent peers to your configuration.

Seeds

Seeds are nodes that provide initial peer discovery. Your node contacts them once to learn about other peers, then disconnects.

# Set seed nodes
SEEDS="<seed-node-id>@seeds.specterchain.com:26656"
sed -i "s/^seeds =.*/seeds = \"$SEEDS\"/" ~/.umbralined/config/config.toml

Persistent Peers

Persistent peers are nodes your node maintains a constant connection to.

# Set persistent peers
PEERS="<peer-id-1>@peer1.specterchain.com:26656,<peer-id-2>@peer2.specterchain.com:26656"
sed -i "s/^persistent_peers =.*/persistent_peers = \"$PEERS\"/" ~/.umbralined/config/config.toml
tip

Check the Specter Discord or the network-config repository for the latest peer list.

Configure Minimum Gas Prices

Set a minimum gas price to protect against spam transactions:

sed -i 's/^minimum-gas-prices =.*/minimum-gas-prices = "0.001aghost"/' ~/.umbralined/config/app.toml

Enable the JSON-RPC Server

If you want your node to serve EVM JSON-RPC queries (required for Web3 applications):

# In app.toml, enable the JSON-RPC server
sed -i '/\[json-rpc\]/,/\[/ s/^enable =.*/enable = true/' ~/.umbralined/config/app.toml
sed -i '/\[json-rpc\]/,/\[/ s/^address =.*/address = "0.0.0.0:8545"/' ~/.umbralined/config/app.toml
sed -i '/\[json-rpc\]/,/\[/ s/^ws-address =.*/ws-address = "0.0.0.0:8546"/' ~/.umbralined/config/app.toml

Start the Node

Direct Execution

umbralined start

Create a systemd service file for automatic restarts and log management:

sudo tee /etc/systemd/system/umbralined.service > /dev/null <<EOF
[Unit]
Description=Specter Node
After=network-online.target

[Service]
User=$USER
ExecStart=$(which umbralined) start
Restart=on-failure
RestartSec=3
LimitNOFILE=65535

Environment="DAEMON_HOME=$HOME/.umbralined"
Environment="DAEMON_NAME=umbralined"

[Install]
WantedBy=multi-user.target
EOF

# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable umbralined
sudo systemctl start umbralined

Viewing Logs

# Follow logs in real time
sudo journalctl -u umbralined -f

# View last 100 lines
sudo journalctl -u umbralined -n 100 --no-pager

Check Sync Status

# Check if the node is catching up
umbralined status | jq '.SyncInfo'

Expected output while syncing:

{
"latest_block_hash": "A1B2C3...",
"latest_app_hash": "D4E5F6...",
"latest_block_height": "123456",
"latest_block_time": "2026-03-16T00:00:00.000000000Z",
"earliest_block_hash": "000000...",
"earliest_app_hash": "",
"earliest_block_height": "1",
"earliest_block_time": "2025-01-01T00:00:00Z",
"catching_up": true
}

When catching_up changes to false, your node is fully synced and following the chain head.

Quick Sync Check

# One-liner to check sync status
umbralined status 2>&1 | jq '.SyncInfo.catching_up'
# Returns: true (still syncing) or false (fully synced)

Check Connected Peers

# View the number of connected peers
umbralined status 2>&1 | jq '.NodeInfo.network'
curl -s http://localhost:26657/net_info | jq '.result.n_peers'

State Sync (Fast Sync)

For faster initial sync, you can use state sync to download a recent snapshot of the chain state instead of replaying all blocks from genesis.

# Get a recent trusted block height and hash from a trusted RPC node
LATEST_HEIGHT=$(curl -s https://testnet.specterchain.com:26657/block | jq -r '.result.block.header.height')
TRUST_HEIGHT=$((LATEST_HEIGHT - 2000))
TRUST_HASH=$(curl -s "https://testnet.specterchain.com:26657/block?height=$TRUST_HEIGHT" | jq -r '.result.block_id.hash')

echo "Trust Height: $TRUST_HEIGHT"
echo "Trust Hash: $TRUST_HASH"

# Configure state sync in config.toml
sed -i '/\[statesync\]/,/\[/ s/^enable =.*/enable = true/' ~/.umbralined/config/config.toml
sed -i "/\[statesync\]/,/\[/ s|^rpc_servers =.*|rpc_servers = \"https://testnet.specterchain.com:26657,https://testnet.specterchain.com:26657\"|" ~/.umbralined/config/config.toml
sed -i "/\[statesync\]/,/\[/ s/^trust_height =.*/trust_height = $TRUST_HEIGHT/" ~/.umbralined/config/config.toml
sed -i "/\[statesync\]/,/\[/ s/^trust_hash =.*/trust_hash = \"$TRUST_HASH\"/" ~/.umbralined/config/config.toml

After configuring state sync, restart the node:

# Reset the data directory (preserves config)
umbralined tendermint unsafe-reset-all --home ~/.umbralined --keep-addr-book

# Start the node
sudo systemctl restart umbralined
caution

State sync only provides a snapshot of the recent state. If you need full historical data (e.g., for an indexer or archive node), you must sync from genesis.

Troubleshooting

Node won't start

# Check for port conflicts
sudo lsof -i :26656 # P2P
sudo lsof -i :26657 # Tendermint RPC
sudo lsof -i :8545 # EVM JSON-RPC
sudo lsof -i :1317 # REST API
sudo lsof -i :9090 # gRPC

No peers found

  • Verify your firewall allows inbound/outbound on port 26656.
  • Confirm seed/peer addresses are correct and reachable.
  • Check that your config.toml has the correct external_address set if behind NAT.
# Set external address if behind NAT
EXTERNAL_IP=$(curl -s https://ifconfig.me)
sed -i "s/^external_address =.*/external_address = \"tcp:\/\/$EXTERNAL_IP:26656\"/" ~/.umbralined/config/config.toml

Node is stuck at a block height

This typically indicates a consensus issue. Check logs for error messages:

sudo journalctl -u umbralined -n 200 --no-pager | grep -i "error\|ERR\|panic"

If the node is stuck due to an app hash mismatch, you may need to reset state and resync:

umbralined tendermint unsafe-reset-all --home ~/.umbralined --keep-addr-book
sudo systemctl restart umbralined