Deploying a full IOTA node on a ROCK64 4GB ARM64 Board

Driven by my curiousity, I was wondering if it would be possible to run a full IOTA node on a rasberry pi. After some research I found out that a full node needs at least 4GB of ram, so I concluded that this wouldn’t be the best thing to do.

I did some more research and found out that there are 4GB ARM devices out there that might do the trick. I chose to buy the Rock64. It had promissing specs, and was cheap as well.
So, my goal was set: Run a full IOTA node on a Rock64 device.

This tutorial is based on a tutorial written by yillkid. I had to change a lot of things in order to make it work for Rock64, but all credits go to him for the initial setup. Please donate to him if you like this tutorial.

Note before I start: Sometimes you will find that you are missing packages. If you execute a command in Linux, and you get a message saying command not found, this means that you’ll need to install it.
This is very simple. All you have to type is:
sudo apt-get install package
Change package with the package you would like to download. Most of the time this is equil to the command. For example: make file could return make: command not found. In this case, type sudo apt-get install make

What do you need?


Installing a Linux Image

I’ve tried multiple Linux images, seeing what would suite best for the IOTA node. I ended up using a minimal version of Debian. You are free to use any version you like, but it could be that you’ll have to make some adjustments to the scripts or install some missing packages yourself.

  • Insert the Micro SD card in your pc and hit flash.
  • Wait for Etcher to finish flashing your drive.
  • Put the SD Card in your Rock64 and power it on
  • Login with root: rock64
  • Password: rock64

Configure Network

In order to make sure we always use the same IP address, we should use a static ip address. But first, we want the device to obtain an unused local ip address.

sudo nano /etc/network/interfaces
  • Replace all the current text with:
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto lo
iface lo inet loopback
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp
  • Hit Ctrl + X
  • type y
  • hit enter

Add a nameserver to the resolv.conf file (Might not be needed)

sudo nano /etc/resolv.conf
If the file is empty, add the following line to the file, if it's not empty, leave it like it is!:
nameserver 8.8.8.8
Save and quit:
Ctrl + X
y
Enter

Connect via SSH (Optional but recommended)

Now that you have your network setup, you have the option to connect to your Rock64 with SSH. This is some sort of remote desktop.
If you want to use SSH, follow these steps. If you don’t want to connect via SSH, you can just continue with Changing Root to the HDD/SDD below.

  • Find out your current ip address:
sudo ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 192.168.1.114 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 xxxx::xxxx:xxxx:xxxx:xxxx prefixlen 64 scopeid 0x20<link>
ether 6e:dc:ee:0d:a2:94 txqueuelen 1000 (Ethernet)
RX packets 16680449 bytes 24520569327 (22.8 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3636875 bytes 623746277 (594.8 MiB)
TX errors 21 dropped 0 overruns 21 carrier 0 collisions 0
device interrupt 39
  • Copy the ip address marked bold above.
  • Now open the network config again, this time to make sure we use a static IP Address.
sudo nano /etc/network/interfaces
  • Replace all the current text with this. Replace ipaddress with the address you just copied.
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address ipaddress
netmask 255.255.255.0
gateway 192.168.1.1

Alright, now we can setup SSH on a static IP address. I used software called PuTTY for my windows machine. It’s free to use.

To setup SSH, follow this tutorial

Changing Root to the HDD/SDD

The next thing we would like to do is changing the root directory from the SD card to the HDD/SSD disc.

To do this, I used a tutorial from pine64.pro. Sadly, this didn’t work for me and it took me quite some time to find out what was wrong. Here’s how I did it:

Follow this tutorial on Pin64.pro

Quick note: Some things have slightly changed since this tutorial, so if something is a little bit different (like not being able to choose primairy or extended partition, and partition sda5 might be called sda2 for you). Don’t worry, think logical and you’ll manage!

Unfortunately, there are some things that don’t work in this tutorial, so we need to alter some things.

Set the correct root folder in the right file

Find the correct UUID of your HDD/SDD:

sudo blkid /dev/sda1 (Or any other name of your HDD/SDD)

Copy the UUID name of your HDD/SDD, for example: UUID=”e1eccc0f-cb29–4adf-ac2a-3bfd10b58370"

sudo nano /boot/efi/extlinux/extlinux.conf
Replace the file with this:
TIMEOUT 30
DEFAULT kernel-4.14
MENU TITLE Rock64 boot options
LABEL kernel-4.14
kernel /Image
initrd /initrd.img
fdt /dtb
append earlycon=uart8250,mmio32,0xff130000 rw root=YOUR_UUID rootwait rootfstype=ext4 init=/sbin/init coherent_pool=1M ethaddr=${ethaddr} eth1addr=${eth1addr} serial=${serial#}
Make sure to replace YOUR_UUID with the UUID line you just copied, for example: root=UUID=”e1eccc0f-cb29–4adf-ac2a-3bfd10b58370"
CTRL X
y
enter
  • Now we need to fix something before we reboot, or we might end up in a locked device. We need to fix the fstab file on the HDD/SDD:
sudo mount /dev/sda1 /mnt
sudo nano /mnt/etc/fstab
Replace EVERYTHING in the file with only this:
LABEL=boot /boot/efi vfat defaults,sync 0 0
sudo reboot
Note: It could be that your Rock64 won’t boot anymore after these changes, or is stuck in a loop. If this is the case, something went wrong with your root=UUID reference, or the last step. You can remove the SD card from your Rock64 and read the extlinux.conf file from your pc. Alter the root label to what it was before:
root=LABEL=linux-root
Save and put the SD card back in your Rock64. It might be that it boots again. If not, something went wrong with the fstab file. This is very tricky to fix. I ended up restarting from scratch. If you have another linux machine, you could try to connect the HDD or SDD to that machine, and alter the /etc/fstab file there.

Check if your root is indeed changed, if not, retry. It took me a while before I rodid everything correct.

df -h
Filesystem      Size  Used Avail Use% Mounted on
udev 2.0G 0 2.0G 0% /dev
tmpfs 393M 11M 383M 3% /run
/dev/sda1 136G 26G 104G 20% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mmcblk1p6 100M 42M 59M 42% /boot/efi
tmpfs 393M 0 393M 0% /run/user/1000

If the name of your HD is assigned to / then you’re good to go. Boot will still be done by the SD card. You can’t change this.


Fix repository Label issue

  • There is a small issue with a label in one of the repositories, preventing you from running apt-get update. To fix it, remove the repository. It will be added automatically again.
sudo add-apt-repository --remove ppa:ayufan/rock64-ppa
sudo apt-get update

Sync the database

Let’s start syncing the database. This will take some time. At the moment of writing this beast is 9–10 GB in size. It is recommanded to do this in a seperated SSH connection, so that you can continue with the installation while it is downloading / unzipping. PuTTY can open multiple sessions with 1 server.

  • Navigate to the folder you want to install RocksDB and Iri to. Then let’s make a new folder where we install everything, in this case named: IOTA
Example: IRI and RocksDB will be installed in /IOTA/
sudo mkdir /IOTA/
cd /IOTA
sudo mkdir mainnetdb
cd mainnetdb
sudo wget https://x-vps.com/iota.db.tgz

It will now start downloading the database. This will take some time. In the mean time you can continue with the section: Install Oracle JAVA 8.

  • After downloading, we can unpack the database file.
  • Make sure you are located in the /IOTA/mainnetdb folder, then run this command:
sudo tar -xvzf iota.db.tgz

Install Oracle JAVA 8

Install the Java Runtime Environment (JRE).

sudo apt-get install default-jre

When prompted, type y for yes to confirm the installation.

Install the JDK (Java Development Kit) with the following command:

sudo apt-get install default-jdk

When prompted to confirm the installation, type y for yes.

Installing the Oracle JDK

sudo apt-get install software-properties-common

When prompted to confirm the installation, type y for yes.

To ensure that we get the correct source line on Debian, we’ll need to run the following command that also modifies the line:

sudo add-apt-repository "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main"

Sometimes, there is a problem with the repositry that we just added. Because it gets updated constantly, errors sneak in. For me it randomly worked one day, and failed the other. Unverified signatures caused me the most problems. To bypass this, we will allow unauthenticated upgrades for once.

sudo apt-get --allow-unauthenticated upgrade

Install Oracle JDK 8:

sudo apt-get install oracle-java8-installer

Again, you’ll be prompted to type y to confirm the install. You’ll also be required to accept the Oracle Binary Code license terms. Use the arrow key to select “Yes”, then press “Enter” to accept the license. 
Once the installation is complete, you can verify your Java version:

javac -version

You’ll receive output similar to this:

Output:
javac 1.8.0_111

As a final step, let’s remove the added repository again, so it won’t bother us in the future anymore:

sudo add-apt-repository --remove "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main"

Reference: How to install java on Debian 8

Install NodeJS and NPM

sudo apt install curl
curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
sudo apt install nodejs
now check if it works:
node --version
should output something similar to:
v6.12.3

Reference: How to install Node.js LTS on Debian 9 stretch


Build RocksDB

  • Clone IOTA-Deploy script and build rocksDB. Building can take some time (+- 1 hour)
  • Make sure you are still located in the install folder, in this case: /IOTA/
Change IOTA to the name of your installation folder!
cd /IOTA/
apt-get install libgflags-dev
sudo git clone https://github.com/PerfectStorm85/iota-deploy
sudo cp iota-deploy/scripts/rocksdb/* .
sudo ./BUILD-rocksdb.sh

Now Deploy the build

cd rocksdb
sudo ./DEPLOY_MAVEN.sh

Install IRI

Make sure we are back in our installation folder (/IOTA/):
cd ..
sudo cp iota-deploy/scripts/iri/* .
sudo ./BUILD-iri.sh [IRI_version_to_build]

I used IRI version 1.4.1.7 because that’s the latest version at the moment of writing. So, replace IRI_version_to_build with 1.4.1.7. For example:

sudo ./BUILD-iri.sh 1.4.1.7

Deploy IRI

Create a configuration file for IRI.

sudo nano iri.ini

Add the following to the file (I will cover the neighbors section later, leave it empty for now):

[IRI]
PORT = 14265
TCP_RECEIVER_PORT = 15600
UDP_RECEIVER_PORT = 14600
NEIGHBORS = <ADD NEIGHBORS HERE, COMMA SEPERATED>
IXI_DIR = ixi
HEADLESS = true
DEBUG = false
ZMQ_ENABLED = true
DB_PATH = mainnetdb

Close the file by pressing CTRL + X, followed by y and enter


Set port forwarding

This section will be a little bit vague, because this needs to be done on your router. Every router is different, so you might end up finding some help on the internet. There are plenty of tutorials on how to do port forwarding.

Make sure you add the following entrees:

  • TCP port 15600 from your static ip address.
  • UDP port 14600 from your static ip address
  • TCP & UDP port 14265 from your static ip address

Setup UFW

  • Install UFW
sudo apt-get install ufw
  • Check the ufw status:
sudo ufw status
  • If it’s inactive, run the following:
sudo ufw enable
  • Now add the ports you want to allow:
sudo ufw allow 14600
sudo ufw allow 15600
sudo ufw allow 14265
sudo ufw allow 14265/tcp
sudo ufw allow 14265/udp

Get your udp and tcp address

Your udp and tcp address are used to connect to neighbors. If you want to add somebody as a neighbor, you should give that person your udp or tcp address and he/she should give you his/hers.

Make sure you both use either tcp or udp. You can’t mix these two.

  • First, lets get your public ip address:
curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//'
  • Your tcp and udp adresses are now:
  • tcp://publicIP:15600
  • udp://publicIP:14600

Adding neighbors

Before we launch IRI, we need to add some neighbors. Go to the discord or slack channel of IOTA and ask for neighbors. Ask for their tcp or udp address, and give your tcp or udp address to them (Again, make sure both of you use either tcp or udp)

Now lets add those addresses in your iri.ini file:

sudo nano iri.ini
[IRI]
PORT = 14265
TCP_RECEIVER_PORT = 15600
UDP_RECEIVER_PORT = 14600
NEIGHBORS = tcp://address1:14600 udp://address2:14602 tcp://address3:156000
IXI_DIR = ixi
HEADLESS = true
DEBUG = false
ZMQ_ENABLED = true
DB_PATH = /IOTA/mainnetdb
  • You can add as many tcp or udp addresses as you want. Seperate them with space.

Launch IRI

Now it’s finally time to launch IRI. Make sure you finished downloading and unpacking the database file before you launch it.

sudo ./run.sh [IRI_VERSION] ./iri.ini
Example:
./run.sh 1.4.1.7 ./iri.ini
Output:
+ pkill -9 java
+ backup_logs
+ mkdir -p LOGS
+ mv 'hs_err_pid*.log' LOGS/
mv: cannot stat 'hs_err_pid*.log': No such file or directory
+ cat nohup.out
+ cp /var/run/iri.pid LOGS/
+ rm -f nohup.out
+ sleep 2
+ nohup java -server -Xmx540m -Xms128m -Xmn1g -Xss512k -Xmn256m -Xincgc -XX:InitiatingHeapOccupancyPercent=0 -XX:MaxMetaspaceSize=256m -XX:ReservedCodeCacheSize=2496k -XX:CodeCacheMinimumFreeSpace=100k -XX:MaxHeapFreeRatio=10 -XX:MinHeapFreeRatio=5 -XX:+UseCompressedOops -Djava.awt.headless=true -jar .//iri-1.4.1.7.jar --config ./iri.ini --remote-limit-api 'removeNeighbors, addNeighbors, setApiRateLimit' --remote
nohup: redirecting stderr to stdout
+ cat nohup.out
OpenJDK 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release
01/23 20:37:18.947 [main] INFO com.iota.iri.IRI - Remote access enabled. Binding API socket to listen any interface.
01/23 20:37:18.961 [main] INFO com.iota.iri.IRI - Welcome to IRI 1.4.1.7
+ pgrep -f iri-1.4.1.7.jar

It will take some time for the database to sync to the latest Milestone.

Usefull commands

  • Node info:
curl http://localhost:14265/ -X POST -H 'Content-Type: application/json' -H 'X-IOTA-API-Version: 1' -d '{"command": "getNodeInfo"}' | jq .
  • Watch Neighbors stats:
curl http://localhost:14265/ -X POST -H 'Content-Type: application/json' -H 'X-IOTA-API-Version: 1' -d '{"command": "getNeighbors"}' | jq .
  • Add neighbor while IRI is running (Change ADDRESS with the tcp or udp address):
curl http://localhost:14265/   -X POST   -H 'Content-Type: application/json'   -H 'X-IOTA-API-Version: 1'   -d '{"command": "addNeighbors", "uris": ["ADDRESS"]}'

Final words

That’s it! You now have your full node running on the smallest device available to run a full node on: Rock64.

It’s been a long ride for me figuring this out. Especially since this was my first linux experience ever.

If you want to donate then feel free to do so, but don’t forget to donate the original creator (yillkid) of the scripts as well (Link on top)

Donate IOTA:

IWYWXFING9VEEXSQDCRRUEBBZECKZUYMKMMFOPDBGZKHKASRYLTEXLGGPUCLUIGDZQXSOWI9UXUNYWFEYZAAKXTEND

Enjoy your node!

Thanks to everybody in the discord channel who helped me setting it up.
Special thanks to:

  • rck
  • bourgh
  • Bob Ross
  • nuriel77
  • Marcus Jang