Setup an Ethereum archive node using Reth on the Orange Pi 5
Tags: ethereum, tutorial, linux, arm
Published: 2023-07-20 16:41:49


In this post we will prepare a custom version of Armbian for the Orange Pi 5, prepare the board's storage and run the [Reth](https://github.com/paradigmxyz/reth) Ethereum execution client in archive mode.

## Context

As the newest Ethereum execution client Reth was released, we wanted to share the instructions required to setup your own archive node at home using the Orange Pi 5 board.

We spent some time figuring out the solution to an issue which prevented the node from running correctly due to the way the Linux distributions for this specific board were configured.

For those of you who are curious, the issue itself is documented [here](https://github.com/paradigmxyz/reth/issues/2211).

In the next sections, we describe what is the required hardware to get the node ready, as well as what change will be made to Linux and how to deploy the archive node.

## Prepare the hardware

To be able to recompile Armbian (the _why_ is explained in the next section) we need to follow the [official documentation](https://docs.armbian.com/Developer-Guide_Build-Preparation/) requirements.
On our side, we used a Thinkpad running Pop OS.

The modified version of the OS needs to be written to an SD card.
On our side, we used a SanDisk Extreme Pro microSDXC 128 GB.

We also need to connect the board to the local network via the ethernet port and to the power using its USB-C port.

In order to store the data of the archive node, we need external SSDs.
On our side, and despite the fact that this is probably not the most optimised solution, we used two NVMe with 2 TB of storage each, connected to the board using a USB Hub.

## Prepare the OS

As briefly mentioned in the first section, we faced an issue the first time we tried to setup the archive node.
MDBX could not set the database size due to the page size being set to 4 KB, restricting the address space to be 512 GB maximum.

So the next question is: _How can we change this page size to be bigger ?_ 🤔
And the answer is: _When compiling the Kernel._ 😶

Thankfully, Armbian provides an excellent and easy-to-use framework to build the distribution and customise the Kernel features - including the page size.

Let's get started:

- On the host machine, plug the micro SD card. Make sure that it is accessible by running the following command:

```shell
lsblk
```

You should see something like this:

```shell
NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda               8:0    1 119.1G  0 disk  
└─sda1            8:1    1 119.1G  0 part  /media/xpanoramix/3137-6438
...
```

- Then, clone the Armbian build framework:

```shell
git clone https://github.com/armbian/build
cd build
```

- Finally, compile the Linux Kernel for the Orange Pi 5 and flash it to the micro SD card:

```shell
./compile.sh \
BOARD=orangepi5 \
BUILD_MINIMAL=yes \
BUILD_DESKTOP=no \
KERNEL_CONFIGURE=yes \
CARD_DEVICE="/dev/sdX" # Replace "sdX" with the one for your micro SD card !
```

Follow the instructions given in the terminal.
Then, you should see the following screen:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e07fb029z1yjanwcd725.png)



Select the only one and let the process continue. After a while, you should see the following screen appear. Select the "**_jammy_**" option:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhl2gjw32oq0ukz65yvb.png)

Let the process continue again, until the following screen appears. Scroll down to "**_Kernel Features_**", press Enter and change the page size from "**_4 KB_**" to "**_64 KB_**".

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aoeqrxgej7mbkvimswcv.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xga61vmkgiu5s2scgce4.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tun841qtuyxv1ctfa9tw.png)

Save the configuration and load it.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7r0ff3gtxkdsm7kz3brv.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lzok43v9q09njbycqzp5.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzplx8vmnn16sa34blco.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1a21oag7y00s87ivtta.png)

Finally, click on the "**_Exit_**" button in the bottom-left and "**_yes_**" on the pop-up window that appears right after.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ez289vaurkil1sug4quu.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x47wzx10uizdipo70nfi.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4oladrnb5qu5negzxq2.png)

From here, we have to wait for a bit of time until the distribution has been compiled.

At the end, the Armbian image will be flashed to the device specified when running the first command.

Remove it from the host machine, put it into the Orange Pi 5 board and connect power to it.

It is now time to configure the archive node.

## Prepare the archive node

In this section, we will do the following things:

1. Configure the SSDs
2. Setup Reth
3. Start the archive node

First and foremost, we need to connect to the board.
You can either use a keyboard + monitor combo or connect using SSH. No matter which solution you decide to use, you'll be forced to choose a new password and create a default user. Just follow those instructions, no need for detailed explanations on this here.

Assuming that we have connected the SSDs to the board, running the `lsblk` command should print something similar to this:

```shell
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    0   1.8T  0 disk
sdb           8:16   0   1.8T  0 disk
mtdblock0    31:0    0    16M  0 disk
mmcblk1     179:0    0 119.1G  0 disk
├─mmcblk1p1 179:1    0   256M  0 part /boot
└─mmcblk1p2 179:2    0 117.6G  0 part /var/log.hdd
                                      /
zram0       254:0    0   7.8G  0 disk [SWAP]
zram1       254:1    0    50M  0 disk /var/log
nvme0n1     259:0    0 119.2G  0 disk
```

Where you can clearly see my two large NVMes at the top.

We will use [lvm](https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)) to "combine" our disks into one.

You can install the `lvm2` tool using the following command:
```shell
apt install lvm2 -y
```

Once installed, you should be able to create the physical volumes using the `pvcreate` command:
```shell
pvcreate /dev/sda /dev/sdb
```

Then, running the `pvdisplay` command should print something similar to this:
```shell
  "/dev/sda" is a new physical volume of "<1.82 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/sda
  VG Name
  PV Size               <1.82 TiB
  Allocatable           NO
  PE Size               0
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               Yx27XD-zoGA-USBi-oHZI-zAmh-tKpe-qLDoar

  "/dev/sdb" is a new physical volume of "<1.82 TiB"
  --- NEW Physical volume ---
  PV Name               /dev/sdb
  VG Name
  PV Size               <1.82 TiB
  Allocatable           NO
  PE Size               0
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               ws3Poe-PE0t-fyQX-l7QT-ncWE-Ym2K-dTdCTg
```

Then, we need to create a volume group called `vg0` using the `vgcreate` command:
```shell
vgcreate vg0 /dev/sda /dev/sdb
```

Again, we can confirm that the volume group was created using the `vgdisplay` command:

```shell
  --- Volume group ---
  VG Name               vg0
  System ID
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  2
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               0
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               <3.64 TiB
  PE Size               4.00 MiB
  Total PE              953864
  Alloc PE / Size       953864 / <3.64 TiB
  Free  PE / Size       0 / 0
  VG UUID               UE9Q3j-2TFe-BvNp-c65E-FCtY-onxA-Rwf40a

```

Almost done with the volumes ! We need to create and format the logical volume called `reth-data` using the `lvcreate` and `mkfs.ext4` commands.
```shell
lvcreate -n reth-data -l 100%FREE vg0
```

(Just running the `lvdisplay` command to confirm that everything went well)
```
  --- Logical volume ---
  LV Path                /dev/vg0/reth-data
  LV Name                reth-data
  VG Name                vg0
  LV UUID                0Eb4Hk-jMfH-xrtl-vIPP-rRYy-FksS-5igxBj
  LV Write Access        read/write
  LV Creation host, time orangepi5, 2023-07-12 12:22:23 +0000
  LV Status              available
  # open                 0
  LV Size                <3.64 TiB
  Current LE             953864
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0
```

```shell
mkfs.ext4 /dev/vg0/reth-data
```

Now we just have to mount the volume and make sure that it will be mounted every time the board starts.

To do that, we need to edit the `/etc/fstab` file and add the following line at the end of it. Note that you can use `nano /etc/fstab` to make the edit if you don't want to be stuck until the end of time in vim:

```txt
/dev/vg0/reth-data /mnt/reth-data ext4 defaults 0 1
```

This will mount the LVM volume at `/mnt/reth-data`, but this location does not exist yet, so we need to create it using the `mkdir` command:

```shell
mkdir /mnt/reth-data
```

Before we jump into deploying Reth, we just need to reboot the system using:

```shell
sudo reboot
```

Connect back to the board, and move into the `/mnt/reth-data` folder. The available space should be huge - you can check this using the `df -h .` command.

```shell
cd /mnt/reth-data/
```

```shell
Filesystem                  Size  Used Avail Use% Mounted on
/dev/mapper/vg0-reth--data  3.6T   28K  3.4T   1% /mnt/reth-data
```

Now is the time to deploy Reth and the monitoring stack.
We will use Docker to run everything inside multiple containers. To install the tool, please refer to the official documentation available [here](https://docs.docker.com/engine/install/ubuntu/).

Once this is done, we can clone the Reth repository:

```shell
git clone https://github.com/paradigmxyz/reth.git
cd reth
```

It is recommended to switch to the latest release:
```
git checkout v0.1.0-alpha.3 # Replace this with the latest release tag.
```

And change a few things in the `Dockerfile`:

- First, the `BUILD_PROFILE`.
```Dockerfile
ARG BUILD_PROFILE=maxperf
# ...
# ...
# Copy reth over from the build stage
COPY --from=builder /app/target/maxperf/reth /usr/local/bin
```

- Then, we can add some Rust flags to enable CPU-specific optimisations: 
```Dockerfile
# Builds dependencies
RUN RUSTFLAGS="-C target-cpu=native" cargo chef cook --profile $BUILD_PROFILE --recipe-path recipe.json

# Build application
COPY . .
RUN RUSTFLAGS="-C target-cpu=native" cargo build --profile $BUILD_PROFILE --locked --bin reth
```

- Finally, expose a new port `8551`:
```Dockerfile
EXPOSE 30303 30303/udp 9001 8545 8546 8551
```

And this is it for the changes.

Now copy and paste the following content into a new `docker-compose.yaml` file in the parent directory (`/mnt/reth-data`):

```yaml
version: "3"

services:
  reth:
    restart: always
    build:
      context: ./reth
      dockerfile: Dockerfile
    networks:
      - reth-net
    ports:
      - "30303:30303"
      - "30303:30303/udp"
      - "9001:9001"
      - "8545:8545"
      - "8546:8546"
      - "8551:8551"
    volumes:
      - ./datadir:/app/datadir/
    command: ["node", "--datadir", "/app/datadir/", "--authrpc.addr", "0.0.0.0", "--http", "--http.addr", "0.0.0.0", "--metrics", "0.0.0.0:9001"]

  lighthouse:
    restart: always
    image: sigp/lighthouse:latest
    networks:
      - reth-net
    volumes:
      - ./datadir:/app/datadir/
    command:
      - "lighthouse"
      - "bn"
      - "--checkpoint-sync-url"
      - "https://mainnet.checkpoint.sigp.io"
      - "--execution-endpoint"
      - "http://reth:8551"
      - "--execution-jwt"
      - "/app/datadir/jwt.hex"

networks:
  reth-net:

volumes:
  datadir:
```

This configuration combine both Reth (the execution client) and lighthouse (the consensus client).
You can start the containers using the following command:

```shell
docker compose up -d
```

And you should see the building process starting. Be patient, this can take a while because we are building the most optimised binary possible of Reth.

Additionally, you can setup a monitoring stack by following the instructions from the official [Reth documentation available here](https://paradigmxyz.github.io/reth/run/observability.html).

And voilà ! Once the node is synced (which should take a few days) we will be able to play with it ! In the meantime, there's nothing better than observing the sync process:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytw776a0s0katn2cg3sd.png)

## Conclusion

In this post, we prepared our own Ethereum archive node, from building the OS with specific features enabled up until we installed and deployed the Reth execution client.

I would like to personally thank [onbjerg](https://github.com/onbjerg) for his help on resolving the issue caused by the incorrect page size. He actually was the one who indirectly made Reth work on the Orange Pi 5 !

Of course, we also want to say thank you to all the Reth contributors ❤️

We hope this helped ! Feel free to reach us out or comment if you have any question 🚀

Written by [0xpanoramix - Luca G.F.](https://twitter.com/0xpanoramix) for [Quartz](https://twitter.com/qu3rtz).