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
- Chain ID: 1315
- Chainlist Link: https://chainlist.org/chain/1315
- Official RPC https://aeneid.storyrpc.io
- Official Explorer:
- Stakeme Explorer: https://aeneid.storyscan.app
- Faucet
- Official Staking Dashboard: https://aeneid.staking.story.foundation/
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
Component | Version | Network |
---|---|---|
Execution Client | v1.1.0 (Cosmas) | Aeneid Testnet |
Consensus Client | v1.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
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
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
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
- Port conflicts: Ensure required ports are not in use by other services
- Insufficient disk space: Verify you have at least 500GB available
- Permission errors: Ensure you're running commands as root or with sudo
- 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:
- Check the logs for error messages
- Verify all prerequisites are met
- Ensure network connectivity and port availability
- Consult the Story Foundation documentation
Note: This guide is for the Aeneid testnet. For mainnet deployment, please refer to the official mainnet documentation.