# Baremetal

## System Requirements

|      CPU     |           OS           |      RAM     |          DISK         |
| :----------: | :--------------------: | :----------: | :-------------------: |
| 8+ cores CPU | Debian 12/Ubuntu 22.04 | => 16 GB RAM | 6TB+ (NVME preffered) |

{% hint style="info" %}
*The Base archive node reached a size of 13TB on November 30th, 2024*
{% endhint %}

## Base <mark style="color:blue;">🔵</mark>

{% hint style="success" %}
Base is a secure, low-cost Ethereum L2 built on Optimism’s open-source [OP Stack](https://stack.optimism.io/). In this guide, Optimism's `op-geth` and `op-node`binaries are built from source to facilitate the node's installation. This method has proved to sync an archive node successfully in \~48 hours using the official snapshot provided by the Base team.
{% endhint %}

{% hint style="warning" %}
Before you start, make sure that you have your own synced Ethereum L1 RPC URL (e.g. Erigon) and L1 Consensus Layer Beacon endpoint (e.g. Lighthouse) ready.
{% endhint %}

## Pre-Requisites

{% code overflow="wrap" %}

```bash
sudo apt update -y && sudo apt upgrade -y && sudo apt autoremove -y

sudo apt install -y git make wget aria2 gcc pkg-config libusb-1.0-0-dev libudev-dev jq gcc g++ curl libssl-dev screen apache2-utils build-essential pkg-config
```

{% endcode %}

### Setting up Firewall

Set explicit default UFW rules

```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
```

Allow SSH

```bash
sudo ufw allow 22/tcp
```

Allow remote RPC connections with Base Node

```bash
sudo ufw allow from ${REMOTE.HOST.IP} to any port 8545
```

{% hint style="warning" %}
Not advised to allow all or unknown IP address to RPC port
{% endhint %}

Enable Firewall

```bash
sudo ufw enable
```

## Download a snapshot

*Create a directory and start downloading an archive in screen session as it takes \~9 hours*

{% code overflow="wrap" %}

```bash
mkdir base && cd base

screen -S archive

aria2c --file-allocation=none -c -x 10 -s 10 "https://base-snapshots-mainnet-archive.s3.amazonaws.com/$(curl https://base-snapshots-mainnet-archive.s3.amazonaws.com/latest)"
```

{% endcode %}

```bash
#to return to previous screen and continue installation press 

Ctrl+a+d
```

## Compile Op-node

### Required Software Dependencies

<table><thead><tr><th width="154">Dependency</th><th width="110" align="center">Version</th><th width="233">Version Check Command</th></tr></thead><tbody><tr><td><mark style="color:green;">go</mark></td><td align="center"><code>^1.22</code></td><td><code>go version</code></td></tr><tr><td><mark style="color:orange;">node</mark></td><td align="center"><code>^20</code></td><td><code>node --version</code></td></tr><tr><td><mark style="color:blue;">pnpm</mark></td><td align="center"><code>^8</code></td><td><code>pnpm --version</code></td></tr><tr><td><mark style="color:green;">foundry</mark></td><td align="center"><code>^0.2.0</code></td><td><code>forge --version</code></td></tr><tr><td><mark style="color:orange;">make</mark></td><td align="center"><code>^4</code></td><td><code>make --version</code></td></tr><tr><td><mark style="color:green;">yarn</mark></td><td align="center"><code>1.22.21</code></td><td><code>yarn --version</code></td></tr><tr><td><mark style="color:blue;">nvm</mark></td><td align="center"><code>0.39.3</code></td><td><code>nvm --verison</code></td></tr></tbody></table>

### Install go

<pre class="language-bash" data-overflow="wrap" data-full-width="false"><code class="lang-bash">sudo wget https://go.dev/dl/go1.22.9.linux-amd64.tar.gz &#x26;&#x26; sudo rm -rf /usr/local/go &#x26;&#x26; sudo tar -C /usr/local -xzf go1.22.9.linux-amd64.tar.gz &#x26;&#x26; rm go1.22.9.linux-amd64.tar.gz

#to verify Go installation
go version

#If it returns Command 'go' not found simply run 
echo 'export PATH=$PATH:/usr/local/go/bin:/root/.local/bin' >> /root/.bashrc
<strong>
</strong><strong>#and then apply changes with
</strong>
source /root/.bashrc
</code></pre>

### Install nvm

```bash
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
```

### Download foundry

```bash
curl -L https://foundry.paradigm.xyz | bash
```

### Install foundry

```bash
source /root/.bashrc #or start a new terminal session to use foundryup

foundryup
```

### Install node and yarn

```bash
nvm install 18.12.0 && npm install --global yarn && nvm use 18.12.0 && npm -g install pnpm

source /root/.bashrc
```

### Check if go and all dependancies are installed

```bash
go version 
nvm -v
npm -v
yarn -v
pnpm -v
```

### Create directories

```bash
mkdir -p /root/github
mkdir -p /root/data/base/geth/op-node
mkdir -p /root/data/base/geth/op-geth
```

### Build op-node

```bash
cd /root/github/

git clone https://github.com/ethereum-optimism/optimism.git

cd optimism

git checkout v1.9.5

make op-node
```

*#The binary is built at /root/github/optimism/op-node/bin/op-node*

### Create systemd service

{% hint style="warning" %}
You'll need your own synced Ethereum L1 RPC URL (e.g. Erigon) and L1 Consensus Layer Beacon endpoint (e.g. Lighthouse) in order to run Base
{% endhint %}

{% code overflow="wrap" %}

```bash
echo "[Unit]
Description=Base OP Node Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000

WorkingDirectory=/root/data/base/geth/op-node
Environment=OP_GETH_GENESIS_FILE_PATH=/root/data/base/geth/op-geth/genesis-l2.json \
OP_GETH_SEQUENCER_HTTP=https://mainnet-sequencer.base.org \
OP_GETH_BOOTNODES=enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301,enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301,enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301,enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301,enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301 \
OP_NODE_L1_ETH_RPC={L1 RPC URL} \
OP_NODE_L1_BEACON={L1 BEACON RPC URL} \
OP_NODE_L2_ENGINE_AUTH= /root/data/base/geth/op-geth/jwt.hex \
OP_NODE_L2_ENGINE_RPC=http://0.0.0.0:8551 \
OP_NODE_LOG_LEVEL=info \
OP_NODE_METRICS_ADDR=0.0.0.0 \
OP_NODE_METRICS_ENABLED=true \
OP_NODE_METRICS_PORT=7200 \
OP_NODE_NETWORK=base-mainnet \
OP_NODE_P2P_AGENT=base \
OP_NODE_P2P_LISTEN_IP=0.0.0.0 \
OP_NODE_P2P_LISTEN_TCP_PORT=9222 \
OP_NODE_P2P_LISTEN_UDP_PORT=9222 \
OP_NODE_ROLLUP_CONFIG=/root/data/base/geth/op-geth/rollup.json \
OP_NODE_P2P_BOOTNODES=enr:-J24QNz9lbrKbN4iSmmjtnr7SjUMk4zB7f1krHZcTZx-JRKZd0kA2gjufUROD6T3sOWDVDnFJRvqBBo62zuF-hYCohOGAYiOoEyEgmlkgnY0gmlwhAPniryHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQKNVFlCxh_B-716tTs-h1vMzZkSs1FTu_OYTNjgufplG4N0Y3CCJAaDdWRwgiQG,enr:-J24QH-f1wt99sfpHy4c0QJM-NfmsIfmlLAMMcgZCUEgKG_BBYFc6FwYgaMJMQN5dsRBJApIok0jFn-9CS842lGpLmqGAYiOoDRAgmlkgnY0gmlwhLhIgb2Hb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJ9FTIv8B9myn1MWaC_2lJ-sMoeCDkusCsk4BYHjjCq04N0Y3CCJAaDdWRwgiQG,enr:-J24QDXyyxvQYsd0yfsN0cRr1lZ1N11zGTplMNlW4xNEc7LkPXh0NAJ9iSOVdRO95GPYAIc6xmyoCCG6_0JxdL3a0zaGAYiOoAjFgmlkgnY0gmlwhAPckbGHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJwoS7tzwxqXSyFL7g0JM-KWVbgvjfB8JA__T7yY_cYboN0Y3CCJAaDdWRwgiQG,enr:-J24QHmGyBwUZXIcsGYMaUqGGSl4CFdx9Tozu-vQCn5bHIQbR7On7dZbU61vYvfrJr30t0iahSqhc64J46MnUO2JvQaGAYiOoCKKgmlkgnY0gmlwhAPnCzSHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQINc4fSijfbNIiGhcgvwjsjxVFJHUstK9L1T8OTKUjgloN0Y3CCJAaDdWRwgiQG,enr:-J24QG3ypT4xSu0gjb5PABCmVxZqBjVw9ca7pvsI8jl4KATYAnxBmfkaIuEqy9sKvDHKuNCsy57WwK9wTt2aQgcaDDyGAYiOoGAXgmlkgnY0gmlwhDbGmZaHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQIeAK_--tcLEiu7HvoUlbV52MspE0uCocsx1f_rYvRenIN0Y3CCJAaDdWRwgiQG \
OP_NODE_RPC_ADDR=0.0.0.0 \
OP_NODE_RPC_PORT=7545 \
OP_NODE_SNAPSHOT_LOG=/tmp/op-node-snapshot-log \
OP_NODE_VERIFIER_L1_CONFS=4 \
OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS=true \
OP_NODE_L1_TRUST_RPC=true

ExecStart=/root/github/optimism/op-node/bin/op-node \
--l1={L1 RPC URL} \
--l1.beacon={L1 BEACON RPC URL} \
--l2=http://0.0.0.0:8551 \
--l2.jwt-secret=/root/data/base/geth/op-geth/jwt.hex \
--rollup.config=/root/data/base/geth/op-geth/rollup.json
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target" > /etc/systemd/system/op-node.service

```

{% endcode %}

```bash
sudo nano /etc/systemd/system/op-node.service #make changes in op-node service file

sudo systemctl daemon-reload #refresh systemd configuration when changes made

sudo systemctl start op-node.service #start op-node

sudo systemctl enable op-node.service #enable op-node service at system startup

sudo journalctl -fu op-node.service #follow logs of op-node service
```

## Compile op-geth

```bash
cd /root/github/

git clone https://github.com/ethereum-optimism/op-geth.git

cd op-geth

git checkout v1.101411.1

make geth
```

*#The binary is built at /root/github/op-geth/build/bin/geth*

#### Create JWT secret file and download genesis and rollup .json files

```bash
cd /root/data/base/geth/op-geth/

openssl rand -hex 32 > /root/data/base/geth/op-geth/jwt.hex

curl -LO https://raw.githubusercontent.com/base-org/node/main/mainnet/genesis-l2.json 
curl -LO https://raw.githubusercontent.com/base-org/node/main/mainnet/rollup.json

```

### Create systemd service

```bash
sudo echo "[Unit]
Description=BASE OP GETH Service
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=3

[Service]
Type=simple
Restart=on-failure
RestartSec=5
TimeoutSec=900
User=root
Nice=0
LimitNOFILE=200000
WorkingDirectory=/root/github/op-geth/build/bin/
ExecStart=/root/github/op-geth/build/bin/geth \
            --datadir=/root/data/base/geth/op-geth \
            --verbosity=3 \
            --http \
            --http.corsdomain=* \
            --http.vhosts=* \
            --http.addr=0.0.0.0 \
            --http.port=8545 \
            --http.api=web3,debug,eth,txpool,net,engine \
            --authrpc.addr=0.0.0.0 \
            --authrpc.port=8551 \
            --authrpc.vhosts=* \
            --authrpc.jwtsecret=/root/data/base/geth/op-geth/jwt.hex \
            --ws \
            --ws.addr=0.0.0.0 \
            --ws.port=8546 \
            --ws.origins=* \
            --ws.api=debug,eth,txpool,net,engine \
            --metrics \
            --metrics.addr=0.0.0.0 \
            --metrics.port=7300 \
            --syncmode=full \
            --gcmode=archive \
            --nodiscover \
            --maxpeers=100 \
            --networkid=8453 \
            --nat=extip:0.0.0.0 \
            --rollup.sequencerhttp=https://mainnet-sequencer.base.org
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target" > /etc/systemd/system/op-geth.service

```

{% hint style="info" %}
If you wish to sync from scratch, consider bootstraping the node first by running

`/root/github/op-geth/build/bin/geth --datadir /root/data/base/geth/op-geth init /root/data/base/geth/op-geth/genesis-l2.json`
{% endhint %}

## Sync using downloaded Snapshot

```bash
screen –r archive

ls #to see the name of downloaded archive

dtrx -f base-mainnet-archive-xxxxxx.tar.gz
```

*#Unzipping takes \~3-4 hrs so you can go touch some grass*

Consider switching screen by pressing`ctrl A+D`to allow a process run in the background

#### After extracting is done move the contents of geth directory into op-geth data directoy:

```bash
mv /root/base/snapshots/mainnet/download/geth/* /root/data/base/geth/op-geth/geth/
```

### Start op-geth

<pre class="language-bash"><code class="lang-bash">sudo systemctl daemon-reload #refresh systemd configuration when changes made

sudo systemctl start op-geth.service #start op-geth

sudo systemctl enable op-geth.service #enable op-geth service at system startup

<strong>sudo journalctl -fu op-geth.service #follow logs of op-geth service
</strong></code></pre>

{% hint style="info" %}
To check or modify `op-geth.service` parameters simply run&#x20;

`sudo nano /etc/systemd/system/op-geth.service`

Ctrl+X and Y to save changes
{% endhint %}

#### You can also run `curl` command in the terminal to check the status of your node

```bash
curl -d '{"id":0,"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false]}' \
  -H "Content-Type: application/json" http://localhost:8545
```

You can see If blocks increase at <https://base.blockscout.com/> by entering returned hash. It means the node is catching up and the setup is successful.

## References

{% embed url="<https://docs.optimism.io/builders/node-operators/tutorials/node-from-source>" %}

{% embed url="<https://github.com/base-org/node>" %}

{% embed url="<https://docs.base.org/tutorials/run-a-base-node>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.infradao.com/archive-nodes-101/base/geth/baremetal.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
