Andreas Antonopoulos tells us "Not your keys, not your Bitcoin". Here's another Bitcoin axiom: "Your hardware. Your node. Your keys. Your Bitcoin."
For your Bitcoin experience to be truly self-sovereign and trustless, you should run nodes on your own hardware and internet connection. BTCPayServer is an excellent way to run Bitcoin & Lightning nodes together. Not only are you validating transactions, you also get the ability to accept Bitcoin (layer 1) and Lightning (layer 2) payments.
To that end, here are instructions to install and host your very own BTCPayServer on a Raspberry Pi. We call it a BTCPi.
The overall process is as follows:
- Purchase and assemble hardware
- Install Raspbian Lite operating system, configure networking
- Install BTCPayServer-Docker
BTCPayServer can be successfully installed on the following hardware:
- Raspberry Pi 3 Model B+
Other requirements are as follows:
- Internet connection
- Static IP
- Domain Name
- Ability to open ports
80
,443
,9735
on your router
Once you have the hardware and other requirements, you're ready to begin!
Step 1 - Configure your domain name.
Login to your domain registrar and create an A
record pointing your domain to the external IP address of your Pi's internet connection:
- IP Address: Visit ipchicken.com or search the web for "what's my ip" from any device on the network
- Domain / Hostname:
btcpay.YourDomain.com
. Name the subdomain where BTCPayServer will run (e.g.btcpay
). - TTL: Shortest, or Default
It can take several hours for DNS changes to propagate worldwide, so you should do this step first.
Step 2 - Assemble your Pi.
Step 3 - Get on a computer with a microSD card slot, or a USB port if you have a USB-microSD adapter. Download and extract Raspbian Buster Lite to this machine.
Step 4 - On this same computer, download and install Etcher. Etcher is used to 'flash' Operating System disk images to SD cards and USB drives.
In this case, we will be using Etcher to flash your microSD card with the downloaded Raspbian Lite OS. Plug in the microSD card, and run Etcher. Select the unzipped Raspbian OS, select your microSD card, and confirm to flash it.
Step 5 - On this same computer, ssh
in the boot partition of the SD card.
- On Mac and Linux, use
touch ssh
in the card's root directory viaTerminal
- On Windows, use
type nul > ssh
in the card's root directory viacmd
Step 6 - Insert your microSD card and flash drive into the Pi; connect the network cable and power supply.
Step 7 - From another computer, use an SSH client (ssh
on Mac and Linux, PuTTY on Windows) to connect to your Raspberry Pi:
- hostname:
raspberrypi.local
- username:
pi
- password:
raspberry
So: ssh [email protected]
.
If raspberrypi.local
doesn't work, you will have to either look up the Pi's IP address on your router, or run ifconfig
on the Pi directly for the eth0
inet
address.
Step 8 -
passwd
Step 9 - Give your Pi a static IP address and a DHCP reservation on your local network, via your router. Optionally, setup WiFi. There are a few different ways to do this and you will find a ton of articles online. Here's a pretty simple one to follow: Setting up Raspberry Pi WiFi with Static IP on Raspbian Stretch Lite.
To get your router's IP:
- On Linux:
ip route | grep default
- On Mac:
netstat -nr | grep default
- On Windows:
ipconfig | findstr /i "Gateway"
Step 10 - Log into your router and forward ports 80
, 443
, and 9735
to your Pi's local IP address. Every router is different and you should be able to find instructions for your router by searching the web for "Port Forwarding + {your router make and model}".
Step 11 - Install fail2ban
and git
.
fail2ban
bans IPs that attempt to connect to your server and show malicious signs. git
allows you to clone and manage repositories on github.com.
So, open a new terminal window and type the following command:
sudo apt update && sudo apt install -y fail2ban git
Step 12 - Install ufw
(Uncomplicated Firewall) and allow only specific ports. UFW is a user-friendly frontend for managing iptables firewall rules and its main goal is to make managing iptables easier, or as the name says: uncomplicated.
Install UFW:
sudo apt install ufw
This command allows SSH connections from your LAN only. Replace 192.168.1.0
with your own subnet:
sudo ufw allow from 192.168.1.0/24 to any port 22
These ports need to be accessible from anywhere (The default subnet is 'any' unless you specify one):
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 9735
Verify your configuration:
sudo ufw status
Enable your firewall:
sudo ufw enable
Step 13 - Reformat flash drive, to be configured as swap space.
The command sudo fdisk -l
shows a list of the connected storage devices. Assuming you only have one flash drive connected, it will be
called /dev/sda
. Double-check that /dev/sda
exists, and that its storage capacity matches your flash memory.
Delete existing flash drive partition:
sudo fdisk /dev/sda
# Press 'd'
# Press 'w'
Create new primary flash drive partition:
sudo fdisk /dev/sda
# Press 'n'
# Press 'p'
# Press '1'
# Press 'enter'
# Press 'enter'
# Press 'w'
Format partition as ext4:
sudo mkfs.ext4 /dev/sda1
# Create folder for mount.
sudo mkdir /mnt/usb
# Look up UUID of flash drive.
UUID="$(sudo blkid -s UUID -o value /dev/sda1)"
# Add mount to fstab.
echo "UUID=$UUID /mnt/usb ext4 defaults,nofail 0" | sudo tee -a /etc/fstab
Test changes to fstab
file:
sudo mount -a
Verify that drive is mounted:
df -h
/dev/sda1
should appear as mounted on /mnt/usb
.
Create symlink to flash drive for Docker:
sudo mkdir /mnt/usb/docker
sudo ln -s /mnt/usb/docker /var/lib/docker
Step 14 - Finally, move Swapfile to USB and increase its size.
Edit its configuration file:
sudo nano /etc/dphys-swapfile
Change the CONF_SWAPFILE line to:
CONF_SWAPFILE=/mnt/usb/swapfile
Change the CONF_SWAPSIZE line to:
CONF_SWAPSIZE=2048
Stop and restart the swapfile service:
sudo /etc/init.d/dphys-swapfile stop
sudo /etc/init.d/dphys-swapfile start
Step 15 - Install BTCPayServer!
Login as root
:
sudo su -
Create a folder for BTCPayServer:
mkdir btcpayserver
cd btcpayserver
Clone the BTCPayServer-Docker repository into the folder:
git clone https://github.com/btcpayserver/btcpayserver-docker
cd btcpayserver-docker
Set your environment variables.
Make sure the BTCPAY_HOST
value uses your own domain & subdomain.
As usual, run each command separately:
export BTCPAY_HOST="btcpay.YourDomain.com"
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_REVERSEPROXY="nginx"
export BTCPAYGEN_LIGHTNING="lnd"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-xs;opt-save-memory"
If you want to use multiple hostnames, add them via the optional BTCPAY_ADDITIONAL_HOSTS
variable:
export BTCPAY_ADDITIONAL_HOSTS="raspberrypi.local,btcpay.local"
In case you want to restrict access to your local network only, please note that you need to use a .local
domain.
Finally, run the BTCPayServer setup script:
. ./btcpay-setup.sh -i
exit
Step 16 - Go to https://btcpay.YourDomain.com
and confirm that your site is up and your nodes are syncing.
Syncing is very slow on a Pi, since each block and transaction needs to go through validation. You can skip this, at your own risk, by using FastSync. Otherwise, simply leave the node running to sync to 100%; this may take weeks.
Setup Complete!
BTCPayServer's complete FastSync documentation is available here.
Please read very carefully to understand what FastSync is and why it's important to verify the UTXO set yourself.
Step 17 - OPTIONAL - FastSync:
cd /root/btcpayserver/btcpayserver-docker
./btcpay-down.sh
cd contrib
cd FastSync
./load-utxo-set.sh
FastSync currently takes about 30 minutes on a high-speed internet connection. After FastSync finishes, run the following command to restart BTCPayServer:
cd ../..
./btcpay-up.sh
By using FastSync, you are exposing yourself to attacks if a malicious UTXO Set snapshot is sent to you.
If you have another trusted node somewhere else, you can check the validity of the UTXO Set gathered by FastSync by following these instructions.
If you don't have the time or patience to build your own BTCPi, there are a few merchants who can build one for you: