Skip to main content

Story Aeneid Testnet Fullnode Setup Guide

This guide will help you set up a full Story node on the Aeneid testnet. Follow these steps carefully to ensure a successful deployment.

Resources

Prerequisites

System Requirements

  • Operating System: Ubuntu 24.04 LTS or Ubuntu 22.04 LTS
  • CPU: 8 dedicated cores minimum
  • Memory: 32GB RAM minimum
  • Storage: 500GB+ NVMe drive with >1000 MiBps write throughput
  • Network: Stable internet connection
  • Access: Root or sudo privileges

Network Information

ComponentVersionNetwork
Execution Clientv1.1.0 (Cosmas)Aeneid Testnet
Consensus Clientv1.3.0 (Polybius)Aeneid Testnet

Required Ports

Execution Client (story-geth)

  • 8545: HTTP JSON-RPC API
  • 8546: WebSocket interface
  • 30303: P2P communication (TCP + UDP)

Consensus Client (story)

  • 26656: P2P consensus communication
  • 26657: Tendermint RPC
  • 26660: Prometheus metrics (optional)

Step 1: System Preparation

Update System Packages

# Switch to root user
sudo -i

Environment Variables

Set these variables at the start of your session. Modify values as needed for your environment.

# Directory for execution client
export EC_DIR=/data/story/execution

# Directory for consensus client
export CC_DIR=/data/story/consensus

# Node binary version tags
export EXECUTION_TAG=1.1.0
export CONSENSUS_TAG=1.3.0

# Node moniker (replace with your preferred name)
export moniker_name=your-node-name

# Cosmovisor variables
export DAEMON_NAME=story
export DAEMON_HOME=$CC_DIR/data
export DAEMON_DATA_BACKUP_DIR=${DAEMON_HOME}/cosmovisor/backup

# Snapshot base directory
export BASE_DIR=/data/story

# Snapshot URLs
export GETH_SNAPSHOT_URL=https://snapshot-aeneid-story.blocknth.com/execution/aeneid-execution.tar.zst
export STORY_SNAPSHOT_URL=https://snapshot-aeneid-story.blocknth.com/consensus/aeneid-consensus.tar.zst

# RPC endpoint for peers
export RPC=https://rpc-aeneid-story.blocknth.com

Install Required Dependencies

apt update
apt install -y \
curl \
git \
make \
jq \
build-essential \
gcc \
unzip \
wget \
lz4 \
aria2 \
gh pv

Install Go go1.22.11

# Remove existing Go installation
rm -rf /usr/local/go

# Download and install Go go1.22.11
curl -Ls https://go.dev/dl/go1.22.11.linux-amd64.tar.gz | tar -xzf - -C /usr/local

# Set up environment variables
echo 'export PATH=$PATH:/usr/local/go/bin' | tee /etc/profile.d/gobinpath.sh
echo 'export PATH=$PATH:$HOME/go/bin' | tee /etc/profile.d/gopath.sh

# Apply changes
source /etc/profile.d/gobinpath.sh
source /etc/profile.d/gopath.sh

Configure Firewall

Open the required ports for p2p port:

# Define your geth and story p2p ports, default: 
GETH_P2P_PORT=30300
STORY_P2P_PORT=26656

ufw allow ${GETH_P2P_PORT} comment "geth P2P port"
ufw allow ${STORY_P2P_PORT} comment "story P2P port"

Step 2: Execution Client Setup

Create Directory Structure

# Create directories
mkdir -pv ~/.story
export EC_DIR=/data/story/execution
mkdir -pv $EC_DIR/data
ln -sv $EC_DIR/data ~/.story/geth

Download and Install story-geth

warning

Note that the binaries are compiled with ubuntu-24.04.1 LTS and go1.22.11. If you are running the client on incompatible machines, please compile the story-geth client from source code by pulling the tag on your machine.

  • Ubuntu 24.04
# show system version
lsb_release -d

cd $EC_DIR
wget https://github.com/piplabs/story-geth/releases/download/v${EXECUTION_TAG}/geth-linux-amd64
mv geth-linux-amd64 geth-v${EXECUTION_TAG} && chmod +x geth-v${EXECUTION_TAG}

# Verify installation
./geth-v${EXECUTION_TAG} version
  • Ubuntu 22.04
# show system version
lsb_release -d

cd $EC_DIR
wget https://github.com/piplabs/story-geth/archive/refs/tags/v${EXECUTION_TAG}.tar.gz
tar -xvf v${EXECUTION_TAG}.tar.gz && rm v${EXECUTION_TAG}.tar.gz && mv $EC_DIR/story-geth-${EXECUTION_TAG} $EC_DIR/story-geth-src-${EXECUTION_TAG}
cd $EC_DIR/story-geth-src-${EXECUTION_TAG} && make geth
mv ./build/bin/geth $EC_DIR/geth-v${EXECUTION_TAG} && chmod +x $EC_DIR/geth-v${EXECUTION_TAG}
rm -rf $EC_DIR/story-geth-src-${EXECUTION_TAG}

# Verify installation
$EC_DIR/geth-v${EXECUTION_TAG} version

Expected output:

Geth
Version: 1.1.0-stable
Architecture: amd64
Go Version: go1.22.11
Operating System: linux

Generate JWT Secret

# Generate random JWT secret
random_hex=$(openssl rand -hex 32)
echo $random_hex > $EC_DIR/.jwt.hex

Create Startup Script

tee ${EC_DIR}/start_node.sh > /dev/null << EOF
#!/bin/bash

VERSION=${EXECUTION_TAG}
DIR=${EC_DIR}

\${DIR}/geth-v\${VERSION} \
--aeneid --syncmode full \
--datadir \${DIR}/data \
--http \
--ws \
--authrpc.jwtsecret=\${DIR}/.jwt.hex \
--authrpc.vhosts="*" \
--metrics \
--metrics.addr "0.0.0.0"
EOF

chmod +x $EC_DIR/start_node.sh
warning

Use the --help command to see more parameters for configuring your node—for example, --http.addr "0.0.0.0" enables external HTTP access. Remember to set up your firewall accordingly.

Create Systemd Service

tee /etc/systemd/system/story-geth.service > /dev/null << EOF
[Unit]
Description=Story Geth Execution Client
After=network-online.target

[Service]
User=root
ExecStart=bash $EC_DIR/start_node.sh
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
WorkingDirectory=${EC_DIR}

[Install]
WantedBy=multi-user.target
EOF

Step 3: Consensus Client Setup

Create Directory Structure

export CC_DIR=/data/story/consensus
mkdir -pv $CC_DIR/data
ln -sv $CC_DIR/data ~/.story/story

Download and Install story

  • Ubuntu 24.04
# show system version
lsb_release -d

cd $CC_DIR
wget https://github.com/piplabs/story/releases/download/v${CONSENSUS_TAG}/story-linux-amd64
mv story-linux-amd64 story && chmod +x story
mv ./story $CC_DIR/story-v${CONSENSUS_TAG} && chmod +x $CC_DIR/story-v${CONSENSUS_TAG}

$CC_DIR/story-v${CONSENSUS_TAG} version
  • Ubuntu 22.04
# show system version
lsb_release -d

cd $EC_DIR
wget https://github.com/piplabs/story/archive/refs/tags/v${CONSENSUS_TAG}.tar.gz
tar -xvf v${CONSENSUS_TAG}.tar.gz && rm v${CONSENSUS_TAG}.tar.gz && mv $CC_DIR/story-${CONSENSUS_TAG} $CC_DIR/story-src-${CONSENSUS_TAG}
cd $CC_DIR/story-src-${CONSENSUS_TAG} && go build -o story ./client
mv ./story $CC_DIR/story-v${CONSENSUS_TAG} && chmod +x $CC_DIR/story-v${CONSENSUS_TAG}
cd $CC_DIR/ && rm -rf $CC_DIR/story-src-${CONSENSUS_TAG}

$CC_DIR/story-v${CONSENSUS_TAG} version

Expected output:

Version  v1.3.0-stable

Install and Configure Cosmovisor

# Install Cosmovisor
go install cosmossdk.io/tools/cosmovisor/cmd/[email protected]

# Verify installation
cosmovisor version

# Set your node moniker (replace 'your-node-name' with your preferred name)
export moniker_name=your-node-name

# Set environment variables
export DAEMON_NAME=story
export DAEMON_HOME=$CC_DIR/data
export DAEMON_DATA_BACKUP_DIR=${DAEMON_HOME}/cosmovisor/backup

# Create necessary directories
mkdir -pv \
$DAEMON_HOME/cosmovisor/backup \
$DAEMON_HOME/data
# Initialize Cosmovisor
cosmovisor init $CC_DIR/story-v${CONSENSUS_TAG}

Expected output:

7:11AM INF checking on the genesis/bin directory module=cosmovisor
7:11AM INF creating directory (and any parents): "/data/story/consensus/data/cosmovisor/genesis/bin" module=cosmovisor
7:11AM INF checking on the genesis/bin executable module=cosmovisor
7:11AM INF copying executable into place: "/data/story/consensus/data/cosmovisor/genesis/bin/story" module=cosmovisor
7:11AM INF making sure "/data/story/consensus/data/cosmovisor/genesis/bin/story" is executable module=cosmovisor
7:11AM INF checking on the current symlink and creating it if needed module=cosmovisor
7:11AM INF the current symlink points to: "/data/story/consensus/data/cosmovisor/genesis/bin/story" module=cosmovisor
7:11AM INF cosmovisor config.toml created at: /data/story/consensus/data/cosmovisor/config.toml module=cosmovisor
# Initialize the node
cosmovisor run init --network aeneid --moniker ${moniker_name}

Expected output:

7:11AM INF running app args=["init","--network","aeneid","--moniker","blocknth-rpc"] module=cosmovisor path=/data/story/consensus/data/cosmovisor/genesis/bin/story
25-07-26 07:11:35.021 INFO Parsed config from flags clean=false encrypt-priv-key=false external-address="" force=false home=/root/.story/story moniker=blocknth-rpc network=aeneid persistent-peers="" rpc-laddr="" seed-mode=false seeds="" trusted-sync=false
25-07-26 07:11:35.021 INFO Initializing story files and directories
25-07-26 07:11:35.021 INFO Ensuring provided home folder does not contain files, since --force=true
25-07-26 07:11:35.021 INFO Generated folder reason=config path=/root/.story/story/config
25-07-26 07:11:35.021 INFO Generated folder reason=snapshot path=/root/.story/story/data/snapshots
25-07-26 07:11:35.021 INFO Overriding node moniker moniker=blocknth-rpc
25-07-26 07:11:35.021 INFO Using network's default P2P seeds seeds=944e8889ecd7c13623ef1081aae4555d6f525041@b1-b.odyssey-devnet.storyrpc.io:26656
25-07-26 07:11:35.022 INFO Generated default comet config file path=/root/.story/story/config/config.toml
25-07-26 07:11:35.023 INFO Generated default story config file path=/root/.story/story/config/story.toml
25-07-26 07:11:35.038 INFO Generated private validator key_file=/root/.story/story/config/priv_validator_key.json state_file=/root/.story/story/data/priv_validator_state.json
25-07-26 07:11:35.038 INFO Generated node key path=/root/.story/story/config/node_key.json
Base64 Encoded Public Key: AqXmeMBUGjn1rFXCMWFOgfbP5WfSlmMaSHS0cocnznEC
25-07-26 07:11:35.038 INFO Generated well-known network genesis file path=/root/.story/story/config/genesis.json

Configure Node Settings

# Get peers from the network
peers=$(curl -sS ${RPC}/net_info | jq -r '.result.peers[] | "\(.node_info.id)@\(.remote_ip):\(.node_info.listen_addr)"' | awk -F ':' '{print $1":"$(NF)}' | paste -sd, -)

# Update persistent peers
sed -i -e "s|^persistent_peers *=.*|persistent_peers = \"$peers\"|" $CC_DIR/data/config/config.toml

# Configure JWT file path
sed -i.bak -e "s|^engine-jwt-file =.*|engine-jwt-file = \"${EC_DIR}/.jwt.hex\"|" $CC_DIR/data/config/story.toml
tip

If you want to customize certain ports, you can manually modify the relevant ports in the story.toml or config.toml

Create Systemd Service

tee /etc/systemd/system/story.service > /dev/null <<EOF
[Unit]
Description=Story Consensus Client
After=network-online.target

[Service]
Type=simple
User=root
Environment="DAEMON_NAME=story"
Environment="DAEMON_HOME=${CC_DIR}/data"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="UNSAFE_SKIP_BACKUP=true"
Environment="DAEMON_DATA_BACKUP_DIR=${CC_DIR}/data/cosmovisor/backup"
ExecStart=/root/go/bin/cosmovisor run run --api-enable --api-address=0.0.0.0:1317
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

Step 4: Download and Restore Snapshots

Download Snapshots

mkdir -pv $BASE_DIR/snapshot && cd $BASE_DIR/snapshot

# Download execution and consensus snapshots
aria2c -c ${GETH_SNAPSHOT_URL} -o geth_snapshot.tar.zst
aria2c -c ${STORY_SNAPSHOT_URL} -o story_snapshot.tar.zst

Restore Snapshots

# Create data directories
mkdir -pv ${EC_DIR}/data/geth ${CC_DIR}/data/data

# Clear existing data
systemctl stop story && systemctl stop story-geth

cp ${CC_DIR}/data/data/priv_validator_state.json ${CC_DIR}/data/
rm -rf ${EC_DIR}/data/geth/*
rm -rf ${CC_DIR}/data/data/*

# Restore execution client snapshot
tar -I zstd -xvf geth_snapshot.tar.zst -C ${EC_DIR}/data/get/

# Restore execution client snapshot
tar -I zstd -xvf story_snapshot.tar.zst -C ${CC_DIR}/data/
cp ${CC_DIR}/data/priv_validator_state.json ${CC_DIR}/data/data/priv_validator_state.json

Step 5: Start Services

Enable and Start Services

# Reload systemd
systemctl daemon-reload

# Start execution client
systemctl enable --now story-geth

# Start consensus client
systemctl enable --now story

Monitor Services

# Check execution client logs
journalctl -u story-geth.service -f -o cat

# Check consensus client logs
journalctl -u story.service -f -o cat

Step 6: Verification

Check Service Status

# Check if services are running
systemctl status story-geth
systemctl status story

Verify Node Sync

# Check execution client sync status
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8545

# Check consensus client sync status
curl http://localhost:26657/status

Configuration Files

You can customize your node settings by modifying these configuration files:

  • $CC_DIR/data/config/config.toml: Network and consensus settings
  • $CC_DIR/data/config/story.toml: Client configuration options
  • $CC_DIR/data/priv_validator_key.json: Validator key (sensitive file)

Troubleshooting

Common Issues

  1. Port conflicts: Ensure required ports are not in use by other services
  2. Insufficient disk space: Verify you have at least 500GB available
  3. Permission errors: Ensure you're running commands as root or with sudo
  4. Network connectivity: Check firewall settings and ensure ports are open

Log Analysis

# View recent logs
journalctl -u story-geth.service --since "1 hour ago"
journalctl -u story.service --since "1 hour ago"

# View error logs only
journalctl -u story-geth.service -p err
journalctl -u story.service -p err

Support

If you encounter issues during setup, please:

  1. Check the logs for error messages
  2. Verify all prerequisites are met
  3. Ensure network connectivity and port availability
  4. Consult the Story Foundation documentation

Note: This guide is for the Aeneid testnet. For mainnet deployment, please refer to the official mainnet documentation.