Ethereum Node on a Raspberry Pi4
There is a wonderful out of the box SD card setup for ETH 1 and ETH 2 Raspberry Pi/Ubuntu nodes from ethereum.org, check those out if you want a simple, stable setup.
https://ethereum.org/en/developers/tutorials/run-node-raspberry-pi/
This tutorial is for those that already have a server setup but would also like to add an Ethereum node and needs to manually setup a Geth (we will be covering ETH 1 in this post).
While it is not recommend to run too much on your Raspberry Pi, Geth can be demanding, we can use the process we learn here for bigger more powerful machines.
The key to this install is adding an additional SSD HDD so let us do that.
Setting Up External SSD
Due to the size of the chain we need a large fast hard drive to store the block data. Another consideration is power consumption of the HDD/SSD, it will need to be powered eternally if the RasPi bus cannot deliver the power necessary. There is a wealth of reviews and specs online that will help you find the right drive, in general and pocket SSD will work just fine.
lsblk
sudo fdisk -l
sudo mkfs.ext4 /dev/sda
Filesystem UUID: a6bf4133-08f8-4b96-8fd5-cfbe14a88297
Manually, mount disk.
sudo mkdir /mnt/ssd
sudo chown -R pi:pi /mnt/ssd/
sudo mount /dev/sda /mnt/ssd
Automatically, configure fstab
to automatically mount the disk when the system starts.
sudo blkid
sudo nano /etc/fstab
...add this at end ...
UUID=a6bf4133-08f8-4b96-8fd5-cfbe14a88297 /mnt/ssd ext4 defaults 0 0
Commit changes with a reboot.
sudo reboot
Verify that the drive started up with the rest of the system.
df -ha /dev/sda
Memory Swap to SSD
Now that we have a fast, large auto-mounting SSD we can use it to do a number of helpful things.
Using it for memory swap is one of those things. Geth can use a lot of memory crunching block so let us use some space on our SSD to alleviate the burden.
sudo nano /etc/dphys-swapfile
... add this to file ...
CONF_SWAPSIZE=8192
CONF_MAXSWAP=8192
CONF_SWAPFILE=/mnt/ssd/swap.file
... save and restart ...
sudo /etc/init.d/dphys-swapfile restart
sudo systemctl status dphys-swapfile.service
Checking Disk Performance
Let check or disk speed to see if we can successfully sync Geth.
Write Test
sudo dd if=/dev/zero of=/mnt/ssd/deleteme.dat bs=32M count=64 oflag=direct
- 64+0 records in
- 64+0 records out
- 2147483648 bytes (2.1 GB, 2.0 GiB) copied, 91.5097 s, 23.5 MB/s
Read Test
sudo dd if=/mnt/ssd/deleteme.dat of=/dev/null bs=32M count=64 iflag=direct
- 64+0 records in
- 64+0 records out
- 2147483648 bytes (2.1 GB, 2.0 GiB) copied, 66.4352 s, 32.3 MB/s
Under 50MB/s is probably a no go, you might not be able to catch up to the head.
Port Forward
30303 from outside.
Stability
sudo nano /boot/config.txt
... add ...
gpu_mem=16
arm_64bit=1
Installing GoLang
Find the current download link for your processor and OS.
mkdir ~/download
cd ~/download
wget https://go.dev/dl/go1.17.7.linux-arm64.tar.gz
sudo tar -C /usr/local -xvf go1.17.7.linux-arm64.tar.gz
sudo chown root:root /usr/local/go
sudo chmod 755 /usr/local/go
sudo nano /etc/profile
... add this at end ...
export PATH=$PATH:/usr/local/go/bin
... save ...
sudo reboot
When it comes back online we can check that Go installed properly with the following command.
go version
go version go1.17.7 linux/arm64
Yay! Now we have go an can build and sync our ETH Node.
Installing Geth from Source
git clone https://github.com/ethereum/go-ethereum.git --branch v1.10.16
cd go-ethereum
make geth
... wait ...
... then move the binary ...
sudo mv ~/go-ethereum/build/bin/geth /usr/local/bin
geth version
- Version: 1.10.16-stable
- Git Commit: 20356e57b119b4e70ce47665a71964434e15200d
- Architecture: arm64
- Go Version: go1.17.7
- Operating System: linux
- GOPATH=
- GOROOT=go
Sync It!
Set a folder on the SDD to hold the ETH files. Then use that folder to sync geth.
sudo mkdir /mnt/ssd/ethereum
sudo chown -R pi:pi /mnt/ssd/ethereum
... test it ...
geth --syncmode snap --cache 1024 --rpc --rpcaddr 0.0.0.0 --datadir /mnt/ssd/ethereum
Ctrl+C to stop so we can setup Geth as startup service. Also Check appendix to see the difference between -syncmode.
Geth Service
sudo nano /etc/systemd/system/geth.service
... add this ...
[Unit]
Description=Geth Node
After=network.target auditd.service
Wants=network.target
[Service]
WorkingDirectory=/home/pi
ExecStart=/usr/local/bin/geth --syncmode snap --cache 1024 --http --http.addr 0.0.0.0 --datadir /mnt/ssd/ethereum
User=pi
Group=pi
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
Alias=geth.service
Run the Daemon
sudo systemctl daemon-reload
sudo systemctl start geth
sudo systemctl enable geth
systemctl status geth.service
tail -f /var/log/syslog
Watch the Daemon Work
Accessing the RPC
To open RPC communication, execute:
$ geth --cache=xxx --syncmode "xxx" --http --http.addr 0.0.0.0
http enable the HTTP-RPC server.
http.addr 0.0.0.0 allow other computers on the network to connect to Geth server.
The node is now accessible on http://<rp4_ip_address>:8545
The rp4_ip_address is accessible with ip command:
You can use https://metamask.io/ to test the node connection.
- Select Custom RPC Network.
- Add your node name and settings and save.
Attaching to the Node
//geth attach geth.ipc
geth attach http://localhost:8545
net.listening # are we able to get connections?
net.peerCount # how many other nodes are we connected to
admin.peers # list of peers we are connected to
admin.nodeInfo # info about the node
eth.syncing # are we syncing? how much work left to do?
Syncing
Just spun it up, so I will report back when it finishes with an update, bug fixes and/or some insights. Probably a couple of days, ciao!
Pfau
References
sudo apt-get install git sysstat -y
htop
vcgencmd measure_temp
https://core-geth.org/setup-on-raspberry-pi
https://greg.jeanmart.me/2020/02/23/running-an-ethereum-full-node-on-a-raspberrypi-4-/
https://raphaelpralat.medium.com/start-an-ethereum-node-on-a-raspberry-pi-4-with-geth-ba13d9f57ef8
https://github.com/ethereum/go-ethereum/issues/16796
#!/bin/bash
## DEFINE PARAMS
SYNCM="--syncmode fast"
CACHE="--cache 256"
GARBC="--gcmode full"
DATAD="--datadir /mnt/Ethereum/geth/datadir"
IDENT="--identity BlockchainCaffe"
#ETHST="--ethstats should be nodename:secret@host:port"
RPC='--rpc --rpccorsdomain "*" --rpcapi="db,eth,net,web3,personal,web3" --allow-insecure-unlock'
WSC='--ws --wsaddr "localhost" --wsport "8546" --wsorigins "*" --wsapi="db,eth,net,web3,personal,web3"'
GETH_PARAMS="$SYNCM $CACHE $GARBC $DATAD $IDENT $ETHST $RPC $WSC"
## SET TIME
ntpdate -s time.nist.gov
## START GETH
eval "/usr/local/bin/geth ${GETH_PARAMS}"
Feb 21 15:56:48 raspberrypi geth[23395]: API AND CONSOLE OPTIONS:
Feb 21 15:56:48 raspberrypi geth[23395]: --ipcdisable Disable the IPC-RPC server
Feb 21 15:56:48 raspberrypi geth[23395]: --ipcpath value Filename for IPC socket/pipe within the datadir (explicit paths escape it)
Feb 21 15:56:48 raspberrypi geth[23395]: --http Enable the HTTP-RPC server
Feb 21 15:56:48 raspberrypi geth[23395]: --http.addr value HTTP-RPC server listening interface (default: "localhost")
Feb 21 15:56:48 raspberrypi geth[23395]: --http.port value HTTP-RPC server listening port (default: 8545)
Feb 21 15:56:48 raspberrypi geth[23395]: --http.api value API's offered over the HTTP-RPC interface
Feb 21 15:56:48 raspberrypi geth[23395]: --http.rpcprefix value HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
Feb 21 15:56:48 raspberrypi geth[23395]: --http.corsdomain value Comma separated list of domains from which to accept cross origin requests (browser enforced)
Feb 21 15:56:48 raspberrypi geth[23395]: --http.vhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost")
Feb 21 15:56:48 raspberrypi geth[23395]: --ws Enable the WS-RPC server
Feb 21 15:56:48 raspberrypi geth[23395]: --ws.addr value WS-RPC server listening interface (default: "localhost")
Feb 21 15:56:48 raspberrypi geth[23395]: --ws.port value WS-RPC server listening port (default: 8546)
Feb 21 15:56:48 raspberrypi geth[23395]: --ws.api value API's offered over the WS-RPC interface
Feb 21 15:56:48 raspberrypi geth[23395]: --ws.rpcprefix value HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.
Feb 21 15:56:48 raspberrypi geth[23395]: --ws.origins value Origins from which to accept websockets requests
Feb 21 15:56:48 raspberrypi geth[23395]: --graphql Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.
Feb 21 15:56:48 raspberrypi geth[23395]: --graphql.corsdomain value Comma separated list of domains from which to accept cross origin requests (browser enforced)
Feb 21 15:56:48 raspberrypi geth[23395]: --graphql.vhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost")
Feb 21 15:56:48 raspberrypi geth[23395]: --rpc.gascap value Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite) (default: 50000000)
Feb 21 15:56:48 raspberrypi geth[23395]: --rpc.evmtimeout value Sets a timeout used for eth_call (0=infinite) (default: 5s)
Feb 21 15:56:48 raspberrypi geth[23395]: --rpc.txfeecap value Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap) (default: 1)
Feb 21 15:56:48 raspberrypi geth[23395]: --rpc.allow-unprotected-txs Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC
Feb 21 15:56:48 raspberrypi geth[23395]: --jspath loadScript JavaScript root path for loadScript (default: ".")
Feb 21 15:56:48 raspberrypi geth[23395]: --exec value Execute JavaScript statement
Feb 21 15:56:48 raspberrypi geth[23395]: --preload value Comma separated list of JavaScript files to preload into the console