Inquiring minds want to know: can you run the ThreeFold famerbot on a Raspberry Pi? The answer is, yes, you can, with a few tweaks from the normal instructions. This method should work with Pi 2, 3, and 4, although I’ve only tested on my Pi 4 so far. Supporting Pi 1 and Zero would be just a bit of extra work, as far as I can see, so drop me a line if you have interest in using one of those models and I’ll see about making it happen.
The tricky part about working with the Pi is that the binary executables we release for Intel and AMD x64 based systems aren’t natively compatible with the ARM based processor in the Pi. To overcome this, we’ll use a combination of recompiled binaries and using an emulator to run the existing binaries, to provide a suitable mix of running services that support a working farmerbot.
For now, I am providing a set of ARM compatible containers hosted in my personal Docker Hub repository. I’ll be working with the dev team to incorporate this into our normal build cycle and our official repositories. If you’d like to see the Docker files that generated these images in the meantime, just let me know.
Prerequisites
To follow this tutorial, you’ll need the following:
- ARM based computer, with at least ARMv7 or higher chip (Pi 2 and later)
- 512mb total RAM (~200mb of free RAM is required to run Docker and farmerbot)
- 1-2gb free storage space
- Debian based operating system like Raspbian/RPi OS or Ubuntu (I tested on 32 bit “Buster” and 64 bit “Bullseye”)
You can use a different OS if you want to, but the needed packages might have different names and there could be some other quirks to account for. We don’t need a desktop, so the using a “lite” or “server” OS image is okay.
Update: There are now two paths to choose from below, the first is the original option, which works on any of the devices and operating systems mentioned above. If you’re not sure, this is the way to go.
The second option is for 64 bit Pis (3 and 4) running a 64 bit operating system. Note that the default Raspberry Pi OS images are 32 bit. You can check by running uname -m
in a terminal. The output on a 64 bit OS will be aarch64
. In that case, you can skip to the 64 bit section below for a bit simpler setup.
Let’s go
I won’t cover the farmerbot setup in detail here. Check the link at the top of the post for written instructions or see my video. The changes necessary to run on a Pi include installing a couple extra packages and making a few changes in the docker-compose.yaml
file. You can follow the normal instructions and come back here to complete the rest just before you run docker compose up
.
Install Docker
While the version of Docker included in the repositories might work, I like to get the latest version using Docker’s install script:
wget -O docker.sh get.docker.com
sudo sh docker.sh
32 Bit OS
The following instructions are especially for 32 bit operating systems, but they will work on a 64 bit OS too. If you do have a 64 bit OS running on your Pi, you can skip to the 64 bit instructions below.
Install QEMU
We’re also going to install QEMU for emulation support inside Docker. This is needed because one component that makes farmerbot work, rmb-peer
, won’t compile natively for 32 bit ARM systems:
sudo apt update
sudo apt install qemu-user-static
While this was not necessary in my own testing, one user reported needing to install binfmt-support
manually as well. You can check if it’s working properly with:
ls /proc/sys/fs/binfmt_misc/
There should be many entries starting with qemu-
. If not, try this:
sudo apt install binfmt-support
Tweaking image paths
Next, we’ll replace a couple of the container images with the versions I built for ARM. Inside the docker-compose.yaml
file, there are four services
. Here’s the breakdown on what happens with each:
-
farmerbot
- replace with native ARM container -
rmb-peer
- specify that the image is for theamd64
platform. Docker will emulate with QEMU even if we don’t do this, but doing so will suppress a warning message -
grid3_client
- replace with native ARM container -
redis
- do nothing, native container already available under same tag
For farmerbot
and grid3_client
, the name and tag for the image will be the same, we’ll just replace the path to point to my personal Docker Hub repository where I’ve uploaded the ARM compatible images.
Here’s the full docker-compose.yaml
with the changed image
lines and the added platform
tag:
services:
farmerbot:
image: scottyeager/farmerbot:0.1.0
restart: always
depends_on:
redis:
condition: service_healthy
rmbpeer:
condition: service_started
grid3_client:
condition: service_healthy
volumes:
- ./config:/farmerbot
command: -c /farmerbot/ --grid3 "http://grid3_client:3000" --redis "redis:6379" --debug --output /farmerbot/farmerbot.log
rmbpeer:
image: ghcr.io/threefoldtech/rmb-peer:v1.0.4
platform: amd64
restart: always
depends_on:
redis:
condition: service_healthy
entrypoint: /bin/sh -c
command: ["/usr/sbin/rmb-peer --redis redis://redis:6379 --mnemonics \"$SECRET\" --relay \"$RELAY\" --substrate \"$SUBSTRATE\" -d"]
grid3_client:
image: scottyeager/grid_http_server:2.0.0-rc8
restart: always
depends_on:
redis:
condition: service_healthy
entrypoint: /bin/sh -c
command: ["echo \"{\\\"network\\\":\\\"$NETWORK\\\",\\\"mnemonic\\\":\\\"$SECRET\\\",\\\"rmb_proxy\\\":false,\\\"storeSecret\\\":\\\"secret\\\",\\\"keypairType\\\":\\\"sr25519\\\"}\" > ~/config.json && yarn grid_http_server -c ~/config.json" ]
ports:
- '3000'
healthcheck:
test: ["CMD-SHELL", "curl --fail -X POST -H \"Content-Type: application/json\" http://127.0.0.1:3000/ping || exit 1"]
interval: 10s
timeout: 3s
retries: 30
redis:
image: redis:7.0.8-alpine
restart: always
ports:
- '6379'
command: --save 20 1
volumes:
- db:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30
volumes:
db:
driver: local
64 Bit OS
On a 64 bit OS, all that’s needed is to replace the container paths with the paths to my ARM container builds. Here’s the complete docker-compose.yaml
:
services:
farmerbot:
image: scottyeager/farmerbot:0.1.0
restart: always
depends_on:
redis:
condition: service_healthy
rmbpeer:
condition: service_started
grid3_client:
condition: service_healthy
volumes:
- ./config:/farmerbot
command: -c /farmerbot/ --grid3 "http://grid3_client:3000" --redis "redis:6379" --debug --output /farmerbot/farmerbot.log
rmbpeer:
image: scottyeager/rmb-peer:1.0.4
restart: always
depends_on:
redis:
condition: service_healthy
entrypoint: /bin/sh -c
command: ["/usr/sbin/rmb-peer --redis redis://redis:6379 --mnemonics \"$SECRET\" --relay \"$RELAY\" --substrate \"$SUBSTRATE\" -d"]
grid3_client:
image: scottyeager/grid_http_server:2.0.0-rc8
restart: always
depends_on:
redis:
condition: service_healthy
entrypoint: /bin/sh -c
command: ["echo \"{\\\"network\\\":\\\"$NETWORK\\\",\\\"mnemonic\\\":\\\"$SECRET\\\",\\\"rmb_proxy\\\":false,\\\"storeSecret\\\":\\\"secret\\\",\\\"keypairType\\\":\\\"sr25519\\\"}\" > ~/config.json && yarn grid_http_server -c ~/config.json" ]
ports:
- '3000'
healthcheck:
test: ["CMD-SHELL", "curl --fail -X POST -H \"Content-Type: application/json\" http://127.0.0.1:3000/ping || exit 1"]
interval: 10s
timeout: 3s
retries: 30
redis:
image: redis:7.0.8-alpine
restart: always
ports:
- '6379'
command: --save 20 1
volumes:
- db:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30
volumes:
db:
driver: local
Run it
Alright that’s it. Now we can run docker compose up
and Docker will take care of the rest.
Wrapping up
While I did my best not to pack this post with details about the problem and process of porting software from one platform to another, there’s more to say on that for anyone who’s curious, and I’m keeping my thoughts on that as a draft for now to maybe add to this post later
Please drop a reply here with any questions and your experience running farmerbot on a Rpi or other ARM based computer. It would be great to generate a collection of reports about what works and try to troubleshoot what doesn’t.