How to set up a bitcoin node on Debian using the official "hardened" systemd unit file, with external storage + testnet
It's your responsibility to handle Bitcoin correctly, failure to do so could cause cybersecurity breaches or financial losses, which you are solely responsible for. You should change all passwords, ensure you have a good firewall configuration, keep up-to-date, only use trusted sources for software and configuration, maintain your hardware, ensure working backups and redundancies, etc. You must also double check that these documents are not outdated, malicious or tampered with. The author(s) of these documents cannot be held responsible for losses or damages arising from use or misuse of the information within.
If you are using a bitcoin node in a commercial setting, you need to think about things like redundancy, uptime and recovery. What would happen if you were relying on a single bitcoin node and it went down? How long will it last if you "set it and forget it"? What if you need to make changes to it later or update it? If you don't have a strategy for this you may run into issues eventually. There are things you can do to improve the setup, that are outside the scope of this document.
We want to use the official unit file for bitcoind
, which claims to be "hardened," while making the least amount of changes. We also want to move bulk blockchain storage off of the root volume and onto mounted storage such as a ZFS dataset or a VM virtual disk. Additionally we want to run the same config side-by-side for Bitcoin's testnet.
Many installation guides online omit all of the "hardening" configuration, which admittedly isn't a magic shield, but I think it's a good idea to follow the official instructions as much as possible.
If additional security is desired, a different user can be provided for mainnet/testnet, or a different machine, etc. There are also probably additional things you can do with cgroups, etc. to help.
Can't use symlinks with StateDirectory=
etc. so we'll use a bind mount. Since systemd runs the show these days we'll try to use systemd to control the bind mount rather than our good old friend /etc/fstab
just to keep things clean. Unfortunately systemd requires special naming rules for the bind mount which includes escaping ordinary things like hyphens which don't normally require escaping.
This is solved with the basic installation instructions in the next section, but here is an example of how that works, in case you want to rename things:
Systemd escaping example (pay attention to shell vs elsewhere):
$ systemd-escape -p --suffix=mount "/var/lib/bitcoind-testnet"
var-lib-bitcoind\x2dtestnet.mount
$ sudo cat /etc/systemd/system/var-lib-bitcoind\\x2dtestnet.mount
...
Where=/var/lib/bitcoind-testnet
...
$ sudo cat /etc/systemd/system/bitcoind-testnet.service
...
After=network-online.target var-lib-bitcoind\x2dtestnet.mount
Wants=network-online.target var-lib-bitcoind\x2dtestnet.mount
...
Some assumptions:
- You should be logged in as a normal user with sudo access.
root
should be properly locked out, proper firewall in place etc.- Path names are "like default" for bitcoind configuration etc. on mainnet, and modified so the directories have
-testnet
at the end of the name on testnet - Mounted bulk storage already set up at
/bitcoin
, we will create and set permission on subdirectoriesmainnet
andtestnet
, you need to create and apply correct permissions etc. on/bitcoin
- Systemd to handle bind mounts
- User named bitcoinuser already set up (don't let this user log in, or use SSH, lock it down as much as possible)
- Assuming certain preferences around OOM killer score and nice value, there are more ways to lock down testnet for example
- Mainnet and testnet will be running the same version of bitcoind
Download, verify and install x86-64 binaries. You should use the latest version, not necessarily what's here. You also need to pay attention to the keys used and the output of the verification, this is your responsibility to ensure security.
sudo apt install git gpg htop
wget https://bitcoincore.org/bin/bitcoin-core-26.0/bitcoin-26.0-x86_64-linux-gnu.tar.gz
wget https://bitcoincore.org/bin/bitcoin-core-26.0/SHA256SUMS
wget https://bitcoincore.org/bin/bitcoin-core-26.0/SHA256SUMS.asc
sha256sum --ignore-missing --check SHA256SUMS
git clone https://github.com/bitcoin-core/guix.sigs
gpg --import guix.sigs/builder-keys/*
gpg --verify SHA256SUMS.asc
If all verification looks good, then proceed to installation of the binaries:
tar -xzvf bitcoin-26.0-x86_64-linux-gnu.tar.gz
sudo install -m 0755 -o root -g root -t /usr/local/bin bitcoin-26.0/bin/*
Set up directories for both mainnet and testnet:
sudo mkdir /bitcoin/mainnet /bitcoin/testnet /etc/bitcoin /run/bitcoind /var/lib/bitcoind /etc/bitcoin-testnet /run/bitcoind-testnet /var/lib/bitcoind-testnet
sudo chown -R bitcoinuser:bitcoinuser /bitcoin/mainnet /bitcoin/testnet /etc/bitcoin /run/bitcoind /var/lib/bitcoind /etc/bitcoin-testnet /run/bitcoind-testnet /var/lib/bitcoind-testnet
sudo chmod 0700 /bitcoin/mainnet /bitcoin/testnet
sudo chmod 0710 /etc/bitcoin /run/bitcoind /var/lib/bitcoind /etc/bitcoin-testnet /run/bitcoind-testnet /var/lib/bitcoind-testnet
Configure mainnet and testnet: (contents are attached alongside this document)
sudo nano /etc/bitcoin/bitcoin.conf
sudo nano /etc/bitcoin-testnet/bitcoin.conf
sudo nano /etc/systemd/system/bitcoind-mainnet.service
sudo nano /etc/systemd/system/bitcoind-testnet.service
sudo nano /etc/systemd/system/var-lib-bitcoind.mount
sudo nano /etc/systemd/system/var-lib-bitcoind\\x2dtestnet.mount
Start up services carefully:
sudo systemctl daemon-reload
sudo systemctl start var-lib-bitcoind.mount var-lib-bitcoind\\x2dtestnet.mount
Check to see if things are OK with the bind mounts before proceeding:
sudo systemctl status var-lib-bitcoind.mount
sudo systemctl status var-lib-bitcoind\\x2dtestnet.mount
If it looks good then proceed to the remaining services and check and enable them:
sudo systemctl start bitcoind-mainnet.service bitcoind-testnet.service
sudo systemctl status bitcoind-mainnet.service
sudo systemctl status bitcoind-testnet.service
sudo systemctl enable bitcoind-mainnet.service bitcoind-testnet.service
sudo journalctl -ef
htop
Do not systemctl enable
the var-lib-bitcoind.mount
or var-lib-bitcoind\\x2dtestnet.mount
units or else it will not survive a reboot.