In honor of Cardano on the rocks

ADA North Pool
6 min readNov 9, 2022

This article is meant as an update on the excellent “CARDANO on the ROCKS” article, historic recap and video by Markus Gufmar from 2019. Here Markus showed that a RockPi 4 with 8GB RAM could run Cardano Node extremely efficiently with under 5watts of energy consumption per node.

If you like this article, consider staking to Ada North Pool (Ticker ANP) either through decentralized wallet staking, or if you are trading on an exchange you can stake directly on as well.

Recently the Rock Pi 5b started shipping, and I was lucky enough to get a few as I have been on the waiting list for it for quite long. It can go up to 32 GB of PDDR4x RAM, but the model mostly available goes up to 16GB ram. The CPU has 4 cores that run at 2.4GHZ and 4 cores that run at 1.8GHZ. Luckily this is exactly within the specifications of the Cardano-node that requires a minimum of 16GB RAM and 1.8GHZ from the CPU.

The front end of an assembled Rock PI 5B board.
The backend of an assembled Rock PI 5B board — yes, I recommend securing the NVMEwith a screw as well, but I did not have one available at the time.

Assembly and installation of OS.
Assembly is fairly straightforward. You can use an SD card or an eMMC card. You will need to be able to flash it with an image through software, in my case, I flashed the Ubuntu 20.04 server image. I had some hiccups in booting up the device at first, as many others have. This is natural with a very new device and will get better once drivers improve. The problem was in how the board auto-negotiated power and could be fixed by booting up first with a “dumb” USB power plug that did not support auto-negotiation. With that, you could boot and access the board from SSH. Then it was a matter of upgrading Ubuntu (sudo apt update, then sudo apt upgrade), and it would work fine on any power device after this. There was also this bug with the fan that you could fix by installing a fan controller. To add the NVME I used lsblk to find the /dev/ path of my NVME and then used mkfs -t ext4 /dev/nvme0n1 to make a file system for the NVME. To mount it I found the UUID with ls -l /dev/disk/by-uuid and then in the file /etc/fstab I added that UUID=*your uuid* /opt ext4 defaults,noatime 0 0

Example of /etc/fstab mounting of nvme

To test I simply ran as sudo mount -a.

Setting up the OS for success.
I installed Glances to be able to view resource usage, as well as jq curl and ne (sudo apt install jq curl ne glances). I use nice editor as my text editor as I am weird and don't use the default Linux text editor :)

To tune the device I installed tuned (sudo apt install tuned tuned-utils tuned-utils-systemtap), enabled it (sudo systemctl enable — now tuned) and selected profile for network latency (sudo tuned-adm profile network-latency). I also added a timesync server with chrony (sudo apt-get install chrony -y) and configured it with my own timesync server together with as shown in the image:

configuration from /etc/chrony/chrony.conf — if you have a timesync server, use your own IP or remove the first line. I use a high poll number since this is not critical pool infrastructure.

Then I added in /etc/sysctl.conf settings to tune TCP performance and make it more secure:

# Use Google's congestion control algorithm
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
#Prevent SYN attack, enable SYNcookies (they will kick-in when the #max_syn_backlog reached)
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096# Disables IP source routing
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Add if ip6 used:
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0# Enable Log Spoofed Packets, Source Routed Packets, Redirect #Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1# Don't relay bootp
net.ipv4.conf.all.bootp_relay = 0# Don't proxy arp for anyone
net.ipv4.conf.all.proxy_arp = 0# Turn on the tcp_timestamps, accurate timestamp make TCP congestion # control algorithms work better
net.ipv4.tcp_timestamps = 1# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1# Enable a fix for RFC1337 - time-wait assassination hazards in TCP
net.ipv4.tcp_rfc1337 = 1# Accept packets with SRR option? No
net.ipv4.conf.all.accept_source_route = 0# Ignore all ICMP ECHO and TIMESTAMP requests sent to it via
# broadcast/multicast

net.ipv4.icmp_echo_ignore_broadcasts = 1# Ignore bad ICMP errors

Then I reloaded the sysctl config by:

sudo sysctl -p /etc/sysctl.conf

Compiling cardano-node and cardano-cli
I followed the guide from, but in the step to build the files, I added in the cabal.project.local two lines:

package cardano-crypto-praos
flags: -external-libsodium-vrf

I also built with the -O2 flag, meaning to compile it with more optimization where it would “Apply every non-dangerous optimization, even if it means significantly longer compile times”.

I also had to fix symbol linking to one of the libraries used by running:

sudo ln -s /usr/local/lib/

The files had to be moved from inside the dist-newstyle folder (I could probably have set the install folder when building), and I copied the cardano-node and cardano-cli binaries to /opt/cardano/bin that I had created and appended the version number 1.35.4. I then made the user rock the owner with sudo chown -R rock:rock /opt/cardano. (I could also have created a cardano user for this).

Setting up scripts and services for cardano-node
I then created the folders db sockets config/node1 and scripts inside the /opt/cardano folder.

example of a folder structure

In the config folder I grabbed the mainnet configuration files inside /config/node1. I then set up a systemd service with sudo ne /etc/systemd/system/adarelay.service and the following configuration:

Example of a systemd service for cardano-node, I might have allowed quite too many files to be opened simultaneously, but this also has hard cap limits in Ubuntu, so should not be a problem.

To enable the systemd for reboots you just run sudo systemctl enable adarelay.service, and you can start and restart it with systemctl restart adarelay.service.

To view the node in the script folder I grabbed the Guild LiveView script.

example of Guild LiveView on a relay synching to Cardano mainnet.

I then edited its env files and made sure it pointed to my renamed binaries as well as the correct port (in my case 8013).

Example of env file settings for Guild LiveView

At this point, you would have a live node contributing to the network after the initial synching period, and that would be fairly optimized for the Rock Pi 5b with the settings in the example above. Here is an example of running a timesync server together with 3 Rock Pi 5b boards that I am using for the different testnets:

Example of Rock Pi 5B boards deployed with a timesync server to run Cardano testnets/mainnet.
Guild LiveView of the launched core node on PreProd, topology should in a more secure environment only use local peers.
Guild LiveView of relay on PreProd with topology p2p as well as local node.
Glances view of the Rock Pi 5B that was running mainnet. 11.3 GB of RAM usage so within the 16GB available.
Same Glances view of the PreProd core node — only uses 1GB of RAM.

Further things to do:
I would next secure SSH, add UFW firewall settings and in general harden and optimize the server. I could also then make this a core node (pool validator), configure the topology and configuration files of the node further, and another fun thing to do would be to add mithril signer support. (Perhaps I will show this in another guide on the preprod testnet).



ADA North Pool 0100000101000100010000010010000001001110010011110101001001010100010010000010000001010000010011110100111101001100