Bitcoin Full Node on RBP3
This guide is obsolete. See the revised version for the newest Raspbian Stretch & Bitcoin v0.15.1.
This guide assumes you’re on MacOS, comfortable with terminal and want to run a headless Bitcoin Full Node on Raspberry Pi 3 and set it up w/o attaching any peripherals to RBP.
The following 3 cases will be covered:
- Bitcoin Node (follow 🐢),
- Bitcoin Node only signalling for UASF BIP148 and BIP149 (follow 🐡),
- Bitcoin Node enforcing UASF BIP148 starting August 1st (follow 🐰).
Note
All lines starting with are run on MacOS. All lines starting with π are run on Raspberry Pi 3.
Note_2
The initial sync will take around 5–6 weeks (as of May 2017), so if you plan on enforcing BIP148 for your transactions, make sure to start it early enough for the sync to complete.
Things you need:
- Raspberry Pi 3;
- MicroSD card (200GB+) — make sure it’s big enough to store entire Bitcoin Blockchain (~140GB as of May 2017) and some fluff (~2GB) — note that the more free space you have on it, the longer your SD card will live;
- a way to plug the micro SD card into your MacBook;
- ethernet cable;
- a router with a spare ethernet port.
Prepare SD card
Get Raspbian Lite image
Either via torrent or by abusing Raspberry Pi Foundation servers.
Put image on the SD card
# extract .img file from .zip archive
~> unzip 2017-04-10-raspbian-jessie-lite.zip
Plug the SD card into your computer and run below to identify the disk of your SD card:
~> diskutil list | grep external
Assuming it’s /dev/disk2
:
# Unmount it
~> diskutil unmountDisk /dev/disk2# Copy image to the SD card
~> sudo dd bs=1m if=2017-04-10-raspbian-jessie-lite.img of=/dev/disk2
For other OSs see here.
Enable ssh
Starting with Raspbian 2016–11–25
SSH is disabled by default. To enable it, a file named ssh
needs to be created in the root of the SD card.
~> diskutil mountDisk /dev/disk2
~> touch /Volumes/boot/ssh
~> diskutil unmountDisk /dev/disk2
More about it here.
Connect & secure Raspberry
Once above is done, put the card into your Raspberry, plug it into the router and power it up.
After a minute or two it should boot up. Now it’s time to find its IP address.
There are multiple ways to do that, the easiest one would probably be logging into your router interface (ex. https://192.168.1.1) and trying to find it there.
If that doesn’t work you can also try:
# MAC prefix 'b8:27:eb:' is reserved for RBP Foundation
# see more: http://hwaddress.com/?q=B827EB000000 ~> arp -a | grep 'b8:27:eb'
Or, if that doesn’t work, you can try nmapping your local network for open 22/tcp
ports:
~> nmap -A 192.168.0-1.* -p T:22 --open
Assuming the IP of your Pi is 192.168.1.102
, ssh
to it (default password: raspberry
):
~> ssh pi@192.168.1.102
Change user password
If you’d rather decrease the chances of your Pi joining the IoS party, change your password right away:
π ~> passwd
π ~> exit
Use keys to auth with ssh
Now that we’ve located the RBP and changed its password, let’s make things more secure.
I use Ed25519 keys and I strongly encourage you to do the same. Here’s an easy why & how to switch guide. That being said, you can pass a path to any key in the command below:
~> ssh-copy-id -i ~/.ssh/id_ed25519.pub pi@192.168.1.102
Next we need to disable password authentication. Either manually:
# edit ssh daemon config file
π ~> sudo nano /etc/ssh/sshd_config# Find `#PasswordAuthentication yes` & below it add:
PasswordAuthentication no# To save and exit press ^x + y + enter
Or using a oneliner:
π ~> sudo sed -i '/#PasswordAuthentication yes/a PasswordAuthentication no' /etc/ssh/sshd_config
Listen to ssh-audit.py
It’s a good tool that offers good advice. If you want to see recommendations it gives, run:
~> git clone git@github.com:arthepsy/ssh-audit.git
~> cd ssh-audit
~> ./ssh-audit.py 192.168.1.102
I won’t go into details here, but to follow its recommendations put this into /etc/ssh/sshd_config
file on RBP3:
# make sure these are in the file and NOT commented out:
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key# make sure these are either gone or commented out:
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key# add the below lines
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
For Termius to work on mobile, you need to add diffie-hellman-group-exchange-sha256
to KexAlgorithms
and hmac-sha-256
to MACs
😭.
For ConnectBot to work on mobile you only need to add hmac-sha2-512
to MACs
😢, as it supports Ed25519
curves.
Reload config of the ssh
daemon:
π ~> sudo service ssh reload
Note: If you disconnect now you will need to remove line containing 192.168.1.102
from ~/.ssh/known_hosts
on your Mac before connecting again.
Configure the Raspberry
Localization, Time Zone, etc…
Run the below and feel free to play with the wizard there. You might want to change time zone and WiFi country. Also, “expanding the filesystem” is no longer necessary, as it happens automatically on the first boot (ref: scroll this to 2016–05–10).
π ~> sudo raspi-config# And if it didn't ask you to, run:
π ~> sudo reboot
Get all the shiny updates
π ~> sudo apt-get update
π ~> sudo apt-get upgrade
Disable SWAP
Constant writing to an SD card can kill it in 30 days (according to the internet), so to minimize writes let’s:
# disable SWAP
π ~> sudo swapoff --all# remove package that manages SWAP altogether
π ~> sudo apt-get remove dphys-swapfile# I had some orphans left and this helped
π ~> sudo apt-get autoremove
Use WiFi instead (optional)
Since RBP3 has WiFi, and ethernet cables are so 90’s, let’s switch to WiFi instead:
# gotta do it as root
π ~> sudo su# will generate network={} structure and save it to the right place
π (root)~> wpa_passphrase "SSID" "password" >> /etc/wpa_supplicant/wpa_supplicant.conf# exit the root shell
π (root)~> exit# Run to make Pi acknowledge changes
π ~> sudo wpa_cli reconfigure
After couple of seconds Pi, should automatically connect to the specified network. To find the new IP you can:
π ~> ip a show wlan0 | grep inet
inet 192.168.1.112/24 brd 192.168.0.255 scope global wlan0
inet6 fe80::9ac9:a0:e042:2da0/64 scope link
Or…
π ~> hostname -I
192.168.1.112
In both cases above the IP is 192.168.1.112
, so:
π ~> exit
~> ssh pi@192.168.1.112
If that succeeded you can get rid of the ethernet cable and from now on just use 192.168.1.112
.
Whether you followed this step or not, everything that follows remains the same.
Finally, the good stuff
The below steps are mostly, but loosely, based on the official UNIX BUILD NOTES.
Dependencies
Before we start, we need to install all required dependencies.
π ~> sudo apt-get install git build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libminiupnpc-dev libzmq3-dev jq
Get Bitcoin Core
For 🐢 and 🐡 go to https://github.com/bitcoin/bitcoin/branches and see what’s the newest non-dev branch. As of May 2017 it’s 0.14
, so:
π ~> cd ~# use https instead of ssh to avoid adding rbp3 key to gh account
π ~> git clone -b 0.14 https://github.com/bitcoin/bitcoin.git
For 🐰 run:
π ~> cd ~
π ~> git clone -b 0.14-BIP148 https://github.com/UASF/bitcoin.git
Berkeley DB (optional)
This very specific version (4.8) of Berkeley db is still needed if you want to have your client with wallet capabilities.
π ~> BITCOIN_ROOT=$(pwd)/bitcoin
π ~> BDB_PREFIX="${BITCOIN_ROOT}/db4"
π ~> mkdir -p $BDB_PREFIXπ ~> wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz'
π ~> echo '12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz' | sha256sum -c
# -> db-4.8.30.NC.tar.gz: OKπ ~> tar -xzvf db-4.8.30.NC.tar.gzπ ~> cd db-4.8.30.NC/build_unix/
π ~> ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX
π ~> make install
Build Bitcoin Core
π ~> cd $BITCOIN_ROOTπ ~> ./autogen.sh# run this if you want wallet or…
π ~> ./configure LDFLAGS="-L${BDB_PREFIX}/lib/" CPPFLAGS="-I${BDB_PREFIX}/include/" CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --enable-cxx --without-gui --disable-shared --with-pic --enable-upnp-default# …this if you don’t
π ~> ./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --enable-cxx --without-gui --disable-shared --with-pic --enable-upnp-default --disable-wallet# this might take a short forever - ~1.5 hr
π ~> make checkπ ~> sudo make install
Configure
Probably the best way to get a well optimised ~/.bitcoin/bitcoin.conf
file is to use the generator that Jameson Lopp was kind enough to create.
That being said, here’s the stuff you need to put there:
daemon=1
dbcache=100
maxorphantx=10
maxmempool=50
maxconnections=40
maxuploadtarget=5000upnp=1
I would recommend against node pruning, however if you don’t have a big enough SD card, add prune=N
to the config file. For example on a 64GB card you could set it to 42GB with:
prune=42000
Signal UASF 🐡
To just signal support for both BIPs add the following lines to the config file:
uacomment=BIP8
uacomment=UASF-SegWit-BIP149
uacomment=UASF-SegWit-BIP148
Run
π ~> bitcoind
Bitcoin server starting
Make sure it works
It might take a few minutes to start. You can watch progress by running:
π ~> tail -f ~/.bitcoin/debug.log
And here’s a couple of other handy commands that you can use later:
π ~> bitcoin-cli getinfo
π ~> bitcoin-cli getnetworkinfo
π ~> bitcoin-cli getwalletinfo
π ~> bitcoin-cli getblockchaininfo
π ~> bitcoin-cli getpeerinfo
Exposing port to the outside world…
In previous steps, MiniUPnP has already been compiled-in and enabled, so let’s check if your node is reachable from the outside with:
π ~> curl -s https://bitnodes.21.co/api/v1/nodes/me-8333/
If the response is {"success":true}
, just skip to the next step.
Otherwise, there are still some things that can be done, but since they’re all very setup-specific, I will just list some ideas that might be worth pursuing:
- Just wait a bit (UPnP is currently renewed every 20 minutes),
- Restart node and wait until it boots up completely,
- Make sure UPnP is enabled on the router,
- Assign a permanent local IP to Raspberry Pi, and
- Manually set up port forwarding (for port
8333
), - Make sure your ISP provides you with a public IP (sometimes it might be possible to get a public/static IP as an additional service for a fee).
Note: If neither of the above worked your node will still connect to 8 peers and, from your perspective, will still be fully functional. The only difference being it will not be able to relay blocks and serve SPV wallets.
Now wait, and wait, and wait…
Now, that the node is running it will download and process the entire Bitcoin blockchain. This process will take over a month. Just leave it running and it will get there eventually.
Run on reboot
To avoid starting the node manually after each reboot add this to cron
file:
π ~> which bitcoind/usr/local/bin/bitcoindπ ~> crontab -e# add this line to the end:
@reboot sleep 8; /usr/local/bin/bitcoind
The sleep 8
part is necessary to avoid this error:
Binding RPC on address 127.0.0.1 port 8333 failed.
Trusted Node
Once the sync completes your Node is ready for the grand cooperation with the excellent Samourai Wallet ❤️. To set it up just follow the simple guide here:
Other thingies
Add some scripts to make the sync bearable
While the sync takes place, to soothe your agitation, you can either monitor the progress
value in ~/.bitcoin/bitcoin.conf
file or append some aliases to either ~/.zshrc
or ~/.bashrc
:
# shows % of blocks processed
alias blocks='BLOCKS_FILE=~/.cache/blocks TOTAL=$(curl -s https://btc.blockr.io/api/v1/block/info/last | jq -r '.data.nb') CURRENT=$(bitcoin-cli getblockcount) && BLOCKSF=$(printf "%.5f%%" "$((100.0 * CURRENT / TOTAL))") && printf "%s → %s\n" "$(cat $BLOCKS_FILE)" $BLOCKSF && echo $BLOCKSF > $BLOCKS_FILE'# turns logged `progress` into %
alias progress='PROG_FILE=~/.cache/progress PROG=$(grep UpdateTip ~/.bitcoin/debug.log T -n1 | cut -d " " -f 12 | cut -d = -f 2) PROGF=$(printf "%.2f%%" "$((PROG * 100))") && printf "%s → %s\n" "$(cat $PROG_FILE)" $PROGF && echo $PROGF > $PROG_FILE'
And run:
π ~> mkdir -p ~/.cache && echo "0%" > ~/.cache/{progress,blocks}
Now, running either progress
or blocks
on RBP will show output in the form of:
<value-when-previously-run> → <current-value>
Make ssh welcome message pretty
There’s no reason to see that awful block of text every time you log in. Making it prettier was inspired with stuff from here.
First, you need to create a file somewhere ex. /tmp/rbp-motd.sh
and paste the below to it.
#!/bin/bash
logo="$(tput setaf 2)
.~~. .~~.
'. \ ' ' / .'$(tput setaf 1)
.~ .~~~..~.
: .~.'~'.~. :
~ ( ) ( ) ~
( : '~'.~.'~' : )
~ .~ ( ) ~. ~ $(tput sgr0)Raspberry Pi$(tput setaf 1)
( : '~' : ) $(tput sgr0)Bitcoin$(tput setaf 1)
'~ .~~~. ~'
'~'
$(tput sgr0)"if [ `whoami` != "root" ]; then
echo "$logo"
echo "Run as sudo to update your motd."
else
echo "$logo" > /etc/motd
/etc/init.d/bootlogs
echo "Updated MOTD. Log in again to see the new logo."
fi
Then:
π ~> chmod a+x /tmp/rbp-motd.sh
π ~> sudo /tmp/rbp-motd.sh
Or, if you’re naïve enough to trust me:
π ~> wget -qO- https://gist.githubusercontent.com/meeDamian/9a98f7ae5aba2090872835e21217fb9e/raw/6631f475fd8fb55685921f411b3c39acb8bf1d87/na%25C3%25AFve-btc.sh | sudo sh
After either, just log in again, and you should be greeted with:
Improvements? Mistakes?
If you’ve found anything incorrect in this guide, or have an idea on how to improve it, feel free to either leave a comment, btc [AT] meedamian.com
or @meeDamian me.
Happy?
If you want to get me a coffee or some AC time in the hot climate of Singapore 🇸🇬 you can send your appreciation to 1DamianM2k8WfNEeJmyqSe2YW1upB7UATx or https://paymentcode.io/+meedamian.
Other Guides…
This is a second guide in a series of planned:
- Litecoin Full Node on RBP3,
- Bitcoin Full Node (with or w/o BIP148 UASF 🙊) on RBP3,
- Add JoinMarket to Bitcoin Full Node,
- Add Lightning Network to #1,
- Proxy node traffic through TOR.