> For the complete documentation index, see [llms.txt](https://unitynodes.gitbook.io/unity-nodes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unitynodes.gitbook.io/unity-nodes/mainnet-network/story-story-1/installation-mainnet.md).

# ⚙️Installation Mainnet

## [🛠️ ](https://docs.lavanet.xyz/access-server-kit) Hardware Requirements

<table><thead><tr><th width="175">Node Type</th><th width="173">CPU</th><th>RAM</th><th>Storage</th></tr></thead><tbody><tr><td>Full (Recommended)</td><td><p></p><p>6 CPU</p></td><td>16GB</td><td>400 GB</td></tr></tbody></table>

**Additional requirements**

<table><thead><tr><th width="186">Chain ID</th><th width="128">Value</th><th width="116">Version tag</th><th width="148">Binary Name</th><th>Binary Home</th></tr></thead><tbody><tr><td>aeneid</td><td><strong>Story-Geth</strong></td><td>v1.2.0</td><td>story-geth</td><td>$HOME/.story</td></tr><tr><td>aeneid</td><td><strong>Story binary</strong></td><td>v1.4.2</td><td>story</td><td>$HOME/.story</td></tr></tbody></table>

#### ⏱️ Installation time: `~10-30 minutes`

{% hint style="info" %}
The installation time depends on many factors, such as your skills, resources and characteristics of your server, the most important: disk speed, internet connection, server load CPU, RAM, so this value may differ from the one indicated by us.
{% endhint %}

## 📝 Manual installation

### 📌**Step 1: Installation packeges and dependencies**

```sh
# Install dependencies for building from source
sudo apt update
sudo apt install -y lz4 jq make git gcc build-essential curl chrony unzip gzip snapd tmux bc

# Install Go
sudo rm -rf /usr/local/go
curl -L https://go.dev/dl/go1.21.6.linux-amd64.tar.gz | sudo tar -xzf - -C /usr/local
echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >> $HOME/.bash_profile
source .bash_profile
```

### 📌**Step 2: Set moniker and install node**

Change MONIKER in variable.

```shell
# Change variables
 echo "export WALLET="wallet"" >> $HOME/.bash_profile
 echo "export MONIKER="test"" >> $HOME/.bash_profile
 echo "export STORY_CHAIN_ID="story-1"" >> $HOME/.bash_profile
 echo "export STORY_PORT="47"" >> $HOME/.bash_profile
 source $HOME/.bash_profile

# Clone project repository
 cd $HOME
 rm -rf story-geth
 git clone https://github.com/piplabs/story-geth.git
 cd story-geth
 git checkout v1.2.0
 make geth
 mv build/bin/geth  $HOME/go/bin/
 [ ! -d "$HOME/.story/story" ] && mkdir -p "$HOME/.story/story"
 [ ! -d "$HOME/.story/geth" ] && mkdir -p "$HOME/.story/geth"

 cd $HOME
 rm -rf story
 git clone https://github.com/piplabs/story
 cd story
 git checkout v1.4.2
 go build -o story ./client
 mkdir -p $HOME/go/bin/
 mv $HOME/story/story $HOME/go/bin/

# Init node
 story init --moniker $MONIKER --network $STORY_CHAIN_ID

# Download addrbook,genesis files
 curl -L https://snapshots.unitynodes.app/story-mainnet/genesis.json > $HOME/.story/story/config/genesis.json
 curl -L https://snapshots.unitynodes.app/story-mainnet/addrbook.json > $HOME/.story/story/config/addrbook.json

# Set seeds and peers
 SEEDS="ef0298ad2c09ec3274405fdd0620ca4e3346992e@story-mainnet-seed.unitynodes.app:47656"
 PEERS=""
 CONFIG="$HOME/.story/story/config/config.toml"
 sed -i -e "/^[p2p]/,/^[/{s/^[[:space:]]*seeds *=.*/seeds = "$SEEDS"/s/^[[:space:]]*persistent_peers *=.*/persistent_peers = "$PEERS"/}" "$CONFIG"

# Set custom ports in story.toml file
 sed -i.bak -e "s%:1317%:43317%g;s%:8551%:47551%g" $HOME/.story/story/config/story.toml

# Set custom ports in config.toml file
 sed -i.bak -e "s%:26658%:47658%g;s%:26657%:47657%g;s%:26656%:47656%g;s%^external_address = ""%external_address = "$(wget -qO- eth0.me):43656"%;s%:26660%:47660%g" $HOME/.story/story/config/config.toml

# Enable prometheus and disable indexing
 sed -i -e "s/prometheus = false/prometheus = true/" $HOME/.story/story/config/config.toml
 sed -i -e "s/^indexer *=.*/indexer = "null"/" $HOME/.story/story/config/config.toml

# Create geth servie file
 sudo tee /etc/systemd/system/story-geth.service > /dev/null <<EOF
 [Unit]
 Description=Story Geth daemon
 After=network-online.target

 [Service]
 User=$USER
 ExecStart=$HOME/go/bin/geth --aeneid --syncmode full --http --http.api eth,net,web3,engine --http.vhosts '*' --http.addr 0.0.0.0 --http.port 43545 --authrpc.port 43551 --ws --ws.api eth,web3,net,txpool --ws.addr 0.0.0.0 --ws.port 43546
 Restart=on-failure
 RestartSec=3
 LimitNOFILE=65535

 [Install]
 WantedBy=multi-user.target
 EOF

# Create story service file
 sudo tee /etc/systemd/system/story.service > /dev/null <<EOF
 [Unit]
 Description=Story Service
 After=network.target

 [Service]
 User=$USER
 WorkingDirectory=$HOME/.story/story
 ExecStart=$(which story) run
 Restart=on-failure
 RestartSec=5
 LimitNOFILE=65535

 [Install]
 WantedBy=multi-user.target
 EOF

# Downoload Story Snapshots
 cp $HOME/.story/story/data/priv_validator_state.json $HOME/.story/story/priv_validator_state.json.backup
 rm -rf $HOME/.story/story/data
 curl https://snapshots-mainnet.unitynodes.app/story-mainnet/story-mainnet-latest.tar.lz4 | lz4 -dc - | tar -xf - -C $HOME/.story/story
 mv $HOME/.story/story/priv_validator_state.json.backup $HOME/.story/story/data/priv_validator_state.json

# Downoload Geth snapshot
 rm -rf $HOME/.story/geth/aeneid/geth/chaindata
 mkdir -p $HOME/.story/geth/aeneid/geth
 curl https://snapshots-mainnet.unitynodes.app/story-mainnet/geth-mainnet-latest.tar.lz4 | lz4 -dc - | tar -xf - -C $HOME/.story/geth/aeneid/geth

# Enable and start systemd service
 sudo systemctl daemon-reload
 sudo systemctl enable story story-geth
 sudo systemctl restart story-geth && sleep 5 && sudo systemctl restart story

# Check logs
 journalctl -u story -u story-geth -f
```

### 📌**Step 3:** Node Health Check

Follow the commands to check if your node is working properly

1. **Check version**

```sh
story version
```

2. **View sync status**

```sh
while true; do 
  local_height=$(story status | jq -r .sync_info.latest_block_height)
  network_height=$(curl -s https://rpc.story-mainnet.unitynodes.com/status | jq -r '.result.sync_info.latest_block_height')
  blocks_left=$((network_height - local_height))

  echo -e "\033[1;33m[Sync Status]\033[0m \033[1;32mNode Height:\033[0m \033[1;37m$local_height\033[0m | \033[1;32mNetwork Height:\033[0m \033[1;37m$network_height\033[0m | \033[1;32mBlocks Left:\033[0m \033[1;31m$blocks_left\033[0m"

  sleep 5
done
```

<mark style="color:red;">**`Blocks left - 0-1`**</mark> everything is fine and your node catches up with the last block of the network.

3. **Check logs story service**

```sh
sudo journalctl -u story.service -f -o cat
```

If your node is installed and fully synchronized with the network, proceed with the creation of the validator.

4. **Check logs story-geth**

```sh
sudo journalctl -u story-geth.service -f -o cat
```

For any questions you may have during installation, please contact our chat team or other project validators.

## &#x20;📝 Create Validator

### 📌**Step 1: View validator key**

```sh
story validator export
```

**Export EVM private key**

```sh
story validator export --export-evm-key
```

**View this private key and make backup**

```sh
cat $HOME/.story/story/config/private_key.txt
```

{% hint style="warning" %}
Save your private key
{% endhint %}

### 📌**Step 2:** Send tokens to your wallet

1. Import your wallet to Metamask using your private key
2. Copy your "EVM" address from the imported wallet

{% hint style="info" %}
To create a validator, you need to have 1024 tokens.
{% endhint %}

### 📌**Step 3:** **Create validator**

**Create a validator locked**

```bash
story validator create --stake 1024000000000000000000 --moniker $MONIKER --chain-id 1514 --unlocked=false
```

**Create a validator unlocked**

```shellscript
story validator create --stake 1024000000000000000000 --moniker $MONIKER --chain-id 1514 --unlocked=true
```

{% hint style="warning" %}
After entering the command, you will receive hash transactions, check the status in the [**explorer** ](https://story.aurascan.io/)if the status is <mark style="color:green;">successful</mark> - you have created a validator.\
You can find your validator here: [e**xplorer** ](https://story.aurascan.io/validators)In the **Active /** **Inactive** lists.
{% endhint %}

### 📌**Step 4: Backup**

If you have successfully created a validator, be sure to save your validator.

Show <mark style="color:red;">**`priv_validator_key.json`**</mark>

```sh
cat $HOME/.story/story/config/priv_validator_key.json
```

{% hint style="warning" %}

SAVE YOUR PRIVATE KEY AFTER ENTERING THE COMMAND\
\
The <mark style="color:red;">**priv\_validator\_key.json**</mark> is the key with which you can always restore the operation of your validator, so keep it and in case of reinstallation/transfer of the validator to another server - transfer it too.

Also remember, if you are a validator with a sufficient number of delegated tokens and you are in an active set, signing blocks, always save <mark style="color:red;">**priv\_validator\_state.json**</mark> - this file contains information about the signed blocks of your validators, and in case of restoring the validator after reinstallation or on another server , this file won't give you the old blocks again, otherwise you'll end up in jail with no way out\
\
💡 Hint:

* *View private key:* `cat $HOME/.story/story/config/priv_validator_key.json`
* *View private state:* `cat $HOME/story/story/config/priv_validator_key.json`
  {% endhint %}

All the useful commands to manage your node in the section -  <mark style="color:blue;">**Useful commands**</mark>
