Extended guide

This commit is contained in:
Sun Knudsen 2022-03-02 07:27:06 -05:00
parent 1eb99d6088
commit c03807d832
No known key found for this signature in database
GPG Key ID: 02C43AD072D57783
9 changed files with 928 additions and 222 deletions

View File

@ -4,7 +4,7 @@ Description: Learn how to self-host hardened Bitcoin node.
Author: Sun Knudsen <https://github.com/sunknudsen>
Contributors: Sun Knudsen <https://github.com/sunknudsen>
Reviewers:
Publication date: 2022-02-10T22:57:23.600Z
Publication date: 2022-03-01T17:31:42.392Z
Listed: true
-->
@ -12,11 +12,12 @@ Listed: true
## Requirements
- [Hardened Debian server](../how-to-configure-hardened-debian-server) or [hardened Raspberry Pi](../how-to-configure-hardened-raspberry-pi) (with at least 4GB of RAM and IPv6 disabled)
- [Hardened Debian server](../how-to-configure-hardened-debian-server/README.md) or [hardened Raspberry Pi](../how-to-configure-hardened-raspberry-pi/README.md) (with at least 4GB of RAM, 1TB of SSD storage and IPv6 disabled)
- Linux or macOS computer
## Caveats
- Steps labelled as “bitcoin-dataset” are only required to bootstrap node using bitcoin-dataset.
- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
- When copy/pasting commands that start with `cat << "EOF"`, select all lines at once (from `cat << "EOF"` to `EOF` inclusively) as they are part of the same (single) command
@ -32,6 +33,8 @@ ssh -i ~/.ssh/pi pi@10.0.1.181
### Step 2: install dependencies
> Heads-up: if `sudo: command not found` is thrown, use `su -` instead.
```console
$ sudo su -
@ -40,13 +43,55 @@ $ apt update
$ apt install -y apt-transport-https build-essential clang cmake curl git gnupg sudo
```
### Step 3: add pi user to sudo group
### Step 3 (bitcoin-dataset): install bitcoin-dataset dependencies
```console
$ apt install -y lz4 transmission-cli transmission-daemon
$ systemctl disable transmission-daemon
$ systemctl stop transmission-daemon
```
### Step 4 (bitcoin-dataset): configure transmission-daemon
#### Increase `rmem_max` and `wmem_max`
```console
$ cat << "EOF" >> /etc/sysctl.conf
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
EOF
$ sysctl -p
```
#### Overwrite default settings
```shell
cat << "EOF" > /etc/transmission-daemon/settings.json
{
"dht-enabled": false,
"encryption": 2,
"message-level": 1,
"pex-enabled": false,
"port-forwarding-enabled": true,
"rpc-authentication-required": false,
"rpc-enabled": true,
"utp-enabled": false
}
EOF
```
### Step 5: add user to sudo group
> Heads-up: replace `pi` with user.
```shell
usermod -aG sudo pi
```
### Step 4: log out and log in to enable sudo privileges
### Step 6: log out and log in to enable sudo privileges
> Heads-up: replace `~/.ssh/pi` with path to private key and `pi@10.0.1.181` with server or Raspberry Pi SSH destination.
@ -60,7 +105,177 @@ $ ssh -i ~/.ssh/pi pi@10.0.1.181
$ sudo su -
```
### Step 5: import Suns PGP public key (used to verify downloads below)
### Step 7: install and configure [WireGuard](https://www.wireguard.com/)
#### Install WireGuard
```console
$ apt update
$ apt install -y openresolv wireguard
```
#### Create and fund [Mullvad](https://mullvad.net/en/) account and [generate](https://mullvad.net/en/account/#/wireguard-config/) WireGuard config
> Heads-up: replace `mullvad-ca10` with Mullvad endpoint, paste Mullvad WireGuard config into `/etc/wireguard/$MULLVAD_ENDPOINT.conf`.
```console
$ MULLVAD_ENDPOINT=mullvad-ca10
$ nano /etc/wireguard/$MULLVAD_ENDPOINT.conf
$ sed -i -E 's/^(Address.*?),.*/\1/' /etc/wireguard/mullvad-*.conf
$ sed -i -E 's/^(AllowedIPs.*?),.*/\1/' /etc/wireguard/mullvad-*.conf
```
#### Enable IP forwarding and configure firewall kill switch
> Heads-up: replace `eth0` with network interface (run `ip a` to find interface).
```console
$ NETWORK_INTERFACE=eth0
$ sed -i -E 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
$ sysctl -p
$ cat << EOF > /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip firewall {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
iif != "lo" ip daddr 127.0.0.0/8 drop
iifname "$NETWORK_INTERFACE" tcp dport 22 accept
ct state established,related accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
oif "lo" accept
oifname "$NETWORK_INTERFACE" udp dport 51820 accept
oifname "$MULLVAD_ENDPOINT" tcp dport { 80, 443 } accept
oifname "$MULLVAD_ENDPOINT" udp dport { 53, 123 } accept
ct state established,related accept
}
}
table ip6 firewall {
chain input {
type filter hook input priority filter; policy drop;
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
}
}
EOF
$ nft -f /etc/nftables.conf
```
#### Enable and start WireGuard
```console
$ systemctl enable wg-quick@$MULLVAD_ENDPOINT
$ systemctl start wg-quick@$MULLVAD_ENDPOINT
$ curl https://am.i.mullvad.net/connected
You are connected to Mullvad (server ca10-wireguard). Your IP address is 89.36.78.152
```
You are connected to Mullvad
👍
### Step 8: install [Cargo](https://doc.rust-lang.org/cargo/index.html)
```console
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:
/root/.rustup
This can be modified with the RUSTUP_HOME environment variable.
The Cargo home directory located at:
/root/.cargo
This can be modified with the CARGO_HOME environment variable.
The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:
/root/.cargo/bin
This path will then be added to your PATH environment variable by
modifying the profile files located at:
/root/.profile
/root/.bashrc
You can uninstall at any time with rustup self uninstall and
these changes will be reverted.
Current installation options:
default host triple: aarch64-unknown-linux-gnu
default toolchain: stable (default)
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1
Rust is installed now. Great!
To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).
To configure your current shell, run:
source $HOME/.cargo/env
$ source $HOME/.cargo/env
```
### Step 9 (bitcoin-dataset): install [b3sum](https://github.com/BLAKE3-team/BLAKE3)
```console
$ cargo install b3sum
Updating crates.io index
Installing b3sum v1.3.1
Installed package `b3sum v1.3.1` (executable `b3sum`)
$ mv /root/.cargo/bin/b3sum /usr/bin/
```
### Step 10: import Suns PGP public key (used to verify downloads below)
```console
$ curl --fail https://sunknudsen.com/sunknudsen.asc | gpg --import
@ -79,7 +294,7 @@ imported: 1
👍
### Step 6: verify integrity of Suns PGP public key (learn how [here](../how-to-encrypt-sign-and-decrypt-messages-using-gnupg-on-macos#verify-suns-pgp-public-key-using-fingerprint))
### Step 11: verify integrity of Suns PGP public key (learn how [here](../how-to-encrypt-sign-and-decrypt-messages-using-gnupg-on-macos#verify-suns-pgp-public-key-using-fingerprint))
```console
$ gpg --fingerprint hello@sunknudsen.com
@ -95,7 +310,7 @@ Fingerprint matches published fingerprints
👍
### Step 7: download and verify [bitcoind.service](./bitcoind.service)
### Step 12: download and verify [bitcoind.service](./bitcoind.service)
```console
$ curl --fail --output /lib/systemd/system/bitcoind.service https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/bitcoind.service
@ -123,7 +338,7 @@ Good signature
👍
### Step 8: download and verify [electrs.service](./electrs.service)
### Step 13: download and verify [electrs.service](./electrs.service)
```console
$ curl --fail --output /lib/systemd/system/electrs.service https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/electrs.service
@ -151,7 +366,34 @@ Good signature
👍
### Step 9: download and verify [tor-client-auth.sh](./tor-client-auth.sh)
### Step 14 (bitcoin-dataset): download and verify [transmission-daemon.service](./transmission-daemon.service)
```console
$ curl --fail --output /lib/systemd/system/transmission-daemon.service https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/transmission-daemon.service
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1598 100 1598 0 0 568 0 0:00:02 0:00:02 --:--:-- 568
$ curl --fail --output /lib/systemd/system/transmission-daemon.service.asc https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/transmission-daemon.service.asc
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
$ gpg --verify /lib/systemd/system/transmission-daemon.service.asc
gpg: assuming signed data in '/lib/systemd/system/transmission-daemon.service'
gpg: Signature made Sun 27 Feb 2022 01:47:27 PM EST
gpg: using EDDSA key 9C7887E1B5FCBCE2DFED0E1C02C43AD072D57783
gpg: Good signature from "Sun Knudsen <hello@sunknudsen.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: E786 274B C92B 47C2 3C1C F44B 8C9C A674 C47C A060
Subkey fingerprint: 9C78 87E1 B5FC BCE2 DFED 0E1C 02C4 3AD0 72D5 7783
```
Good signature
👍
### Step 15: download and verify [tor-client-auth.sh](./tor-client-auth.sh)
```console
$ curl --fail --output /usr/bin/tor-client-auth.sh https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/tor-client-auth.sh
@ -181,112 +423,9 @@ Good signature
👍
### Step 10: install and configure [WireGuard](https://www.wireguard.com/)
### Step 16: install and configure [Tor](https://www.torproject.org/)
#### Install WireGuard
```console
$ apt update
$ apt install -y openresolv wireguard
```
#### Create and fund [Mullvad](https://mullvad.net/en/) account and [generate](https://mullvad.net/en/account/#/wireguard-config/) WireGuard config
> Heads-up: replace `mullvad-ca10` with Mullvad endpoint, paste Mullvad WireGuard config into `/etc/wireguard/$MULLVAD_ENDPOINT.conf` and remove IPv6 addresses.
```console
$ MULLVAD_ENDPOINT=mullvad-ca10
$ nano /etc/wireguard/$MULLVAD_ENDPOINT.conf
```
#### Enable IP forwarding and configure firewall as kill switch
> Heads-up: replace `eth0` with network interface
```console
$ NETWORK_INTERFACE=eth0
$ sed -i -E 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
$ sysctl -p
$ cat << EOF > /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip firewall {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
iif != "lo" ip daddr 127.0.0.0/8 drop
iifname $NETWORK_INTERFACE tcp dport 22 accept
ct state established,related accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
oif "lo" accept
oifname $NETWORK_INTERFACE udp dport 51820 accept
oifname $MULLVAD_ENDPOINT tcp dport { 80, 443 } accept
oifname $MULLVAD_ENDPOINT udp dport { 53, 123 } accept
ct state established,related accept
}
}
table ip6 firewall {
chain input {
type filter hook input priority filter; policy drop;
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
}
}
EOF
$ nft -f /etc/nftables.conf
```
#### Enable and start WireGuard
```console
$ systemctl enable wg-quick@$MULLVAD_ENDPOINT
$ systemctl start wg-quick@$MULLVAD_ENDPOINT
$ curl https://am.i.mullvad.net/connected
You are connected to Mullvad (server ca10-wireguard). Your IP address is 89.36.78.152
```
You are connected to Mullvad (server ca10-wireguard).
👍
### Step 11: temporarily allow peer-to-peer over Mullvad
> Heads-up: replace `mullvad-ca10` with Mullvad endpoint.
```console
$ MULLVAD_ENDPOINT=mullvad-ca10
$ nft add rule ip firewall input oifname $MULLVAD_ENDPOINT tcp dport 8333 accept
$ nft add rule ip firewall output oifname $MULLVAD_ENDPOINT tcp dport 8333 accept
```
### Step 12: install and configure [Tor](https://www.torproject.org/)
> Heads-up: replace `bullseye` with server or Raspberry Pi release codename.
> Heads-up: replace `bullseye` with Debian version codename (run `cat /etc/os-release` to find Debian version codename).
```console
$ DEBIAN_CODENAME=bullseye
@ -321,7 +460,7 @@ EOF
$ systemctl restart tor
```
### Step 13: configure Tor hidden services client authorization (see [docs](https://community.torproject.org/onion-services/advanced/client-auth/))
### Step 17: configure Tor hidden services client authorization (see [docs](https://community.torproject.org/onion-services/advanced/client-auth/))
```console
$ cd /var/lib/tor/ssh
@ -335,16 +474,157 @@ $ tor-client-auth.sh
$ systemctl restart tor
$ cd
$ pwd
/root
```
/root
### Step 18: create bitcoin user
```console
$ adduser --group --no-create-home --system bitcoin
Adding system user `bitcoin' (UID 110) ...
Adding new group `bitcoin' (GID 115) ...
Adding new user `bitcoin' (UID 110) with group `bitcoin' ...
Not creating home directory `/home/bitcoin'.
$ usermod -aG debian-tor bitcoin
```
### Step 19 (bitcoin-dataset): download and verify bitcoin-dataset torrent
```console
$ curl --fail --remote-name https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/bitcoin-dataset.torrent
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4271k 100 4271k 0 0 3911k 0 0:00:01 0:00:01 --:--:-- 3911k
$ curl --fail --remote-name https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/bitcoin-dataset.torrent.asc
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 228 100 228 0 0 740 0 --:--:-- --:--:-- --:--:-- 740
$ gpg --verify bitcoin-dataset.torrent.asc
gpg: assuming signed data in 'bitcoin-dataset.torrent'
gpg: Signature made Tue 01 Mar 2022 10:46:35 AM EST
gpg: using EDDSA key 9C7887E1B5FCBCE2DFED0E1C02C43AD072D57783
gpg: Good signature from "Sun Knudsen <hello@sunknudsen.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: E786 274B C92B 47C2 3C1C F44B 8C9C A674 C47C A060
Subkey fingerprint: 9C78 87E1 B5FC BCE2 DFED 0E1C 02C4 3AD0 72D5 7783
```
Good signature
👍
### Step 14: install [Bitcoin Core](https://github.com/bitcoin/bitcoin)
### Step 20 (bitcoin-dataset): temporarily allow BitTorrent peer-to-peer over Mullvad
> Heads-up: replace `mullvad-ca10` with Mullvad endpoint.
```console
$ MULLVAD_ENDPOINT=mullvad-ca10
$ nft add rule ip firewall output oifname $MULLVAD_ENDPOINT tcp dport { 51413, 57715 } accept
```
### Step 21 (bitcoin-dataset): download bitcoin-dataset
> Heads-up: downloading bitcoin-dataset will likely take more than 24 hours on Raspberry Pi.
> Heads-up: if download doesnt start or hangs, try running `systemctl restart transmission-daemon`.
```console
$ systemctl start transmission-daemon
$ transmission-remote --add bitcoin-dataset.torrent --start
$ watch transmission-remote --list
Every 2.0s: transmission-remote --list debian: Tue Mar 1 11:56:05 2022
ID Done Have ETA Up Down Ratio Status Name
1 100% 458.4 GB Done 0.0 0.0 0.0 Idle bitcoin-dataset
Sum: 458.4 GB 0.0 0.0
```
100%
👍
### Step 22 (bitcoin-dataset): stop transmission-daemon
```shell
systemctl stop transmission-daemon
```
### Step 23 (bitcoin-dataset): verify bitcoin-dataset checksums
```console
$ cd /var/lib/transmission-daemon/downloads/bitcoin-dataset
$ gpg --verify BLAKE3CHECKSUMS.asc
```
Good signature
👍
### Step 24 (bitcoin-dataset): check integrity of bitcoin-dataset
> Heads-up: checking integrity of bitcoin-dataset will likely take more than 15 minutes on Raspberry Pi.
```console
$ b3sum --check BLAKE3CHECKSUMS
bitcoin.tar.lz4.part00: OK
electrs.tar.lz4.part03: OK
```
OK
👍
### Step 25 (bitcoin-dataset): extract bitcoin-dataset
> Heads-up: extracting bitcoin-dataset will likely take more than two hours on Raspberry Pi.
```console
$ mkdir -m 710 -p /var/lib/bitcoind /var/lib/electrs
$ for part in bitcoind.tar.lz4.part*; do
cat < "$part" || break
rm -f -- "$part"
done |
tar \
--extract \
--directory /var/lib/bitcoind \
--use-compress-program lz4 \
--verbose
$ for part in electrs.tar.lz4.part*; do
cat < "$part" || break
rm -f -- "$part"
done |
tar \
--extract \
--directory /var/lib/electrs \
--use-compress-program lz4 \
--verbose
$ cd
```
### Step 26: temporarily allow Bitcoin peer-to-peer over Mullvad
> Heads-up: replace `mullvad-ca10` with Mullvad endpoint.
```console
$ MULLVAD_ENDPOINT=mullvad-ca10
$ nft add rule ip firewall input oifname $MULLVAD_ENDPOINT tcp dport 8333 accept
$ nft add rule ip firewall output oifname $MULLVAD_ENDPOINT tcp dport 8333 accept
```
### Step 27: install [Bitcoin Core](https://github.com/bitcoin/bitcoin)
> Heads-up: replace `22.0` with [latest release](https://bitcoincore.org/en/releases/) semver.
@ -480,30 +760,81 @@ server=1
txindex=1
EOF
$ adduser --group --no-create-home --system bitcoin
Adding system user `bitcoin' (UID 110) ...
Adding new group `bitcoin' (GID 115) ...
Adding new user `bitcoin' (UID 110) with group `bitcoin' ...
Not creating home directory `/home/bitcoin'.
$ usermod -aG debian-tor bitcoin
$ systemctl enable bitcoind
$ systemctl start bitcoind
```
### Step 15: watch initial block download
### Step 28: watch initial block download
> Heads-up: initial block download will likely take more than a week on Raspberry Pi.
> Heads-up: initial block download will likely take more than a week on Raspberry Pi unless node was bootstrapped using bitcoin-dataset.
```console
$ sudo -u bitcoin watch bitcoin-cli -datadir=/var/lib/bitcoind getblockchaininfo
Every 2.0s: bitcoin-cli -datadir=/var/lib/bitcoind getblockchaininfo
{
"chain": "main",
"blocks": 724597,
"headers": 724597,
"bestblockhash": "00000000000000000006913cd13692e0c63a569a5aa1ef869d019de317cca732",
"difficulty": 27967152532434.23,
"mediantime": 1645610491,
"verificationprogress": 0.9999997584389468,
"initialblockdownload": false,
"chainwork": "00000000000000000000000000000000000000002934d1f8be10aff1a80e6806",
"size_on_disk": 445562831844,
"pruned": false,
"softforks": {
"bip34": {
"type": "buried",
"active": true,
"height": 227931
},
"bip66": {
"type": "buried",
"active": true,
"height": 363725
},
"bip65": {
"type": "buried",
"active": true,
"height": 388381
},
"csv": {
"type": "buried",
"active": true,
"height": 419328
},
"segwit": {
"type": "buried",
"active": true,
"height": 481824
},
"taproot": {
"type": "bip9",
"bip9": {
"status": "active",
"start_time": 1619222400,
"timeout": 1628640000,
"since": 709632,
"min_activation_height": 709632
},
"height": 709632,
"active": true
}
},
"warnings": ""
}
```
### Step 16: switch to Tor-only (see [docs](https://github.com/bitcoin/bitcoin/blob/master/doc/tor.md))
`"blocks": 724597` = `"headers": 724597` and `"initialblockdownload": false`
> Heads-up: only run following once `"initialblockdownload": false`.
👍
### Step 29: switch to Tor-only (see [docs](https://github.com/bitcoin/bitcoin/blob/master/doc/tor.md))
> Heads-up: only run following once `"blocks": 724597` = `"headers": 724597` and `"initialblockdownload": false`.
```console
$ systemctl stop bitcoind
@ -525,100 +856,31 @@ EOF
$ systemctl start bitcoind
```
### Step 17: install [electrs](https://github.com/romanz/electrs) (see [docs](https://github.com/romanz/electrs/blob/master/doc/install.md))
### Step 30: install [electrs](https://github.com/romanz/electrs) (see [docs](https://github.com/romanz/electrs/blob/master/doc/install.md))
> Heads-up: build will likely take more than half and hour on Raspberry Pi.
```console
$ exit
$ whoami
pi
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
info: downloading installer
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
Rustup metadata and toolchains will be installed into the Rustup
home directory, located at:
/home/pi/.rustup
This can be modified with the RUSTUP_HOME environment variable.
The Cargo home directory located at:
/home/pi/.cargo
This can be modified with the CARGO_HOME environment variable.
The cargo, rustc, rustup and other commands will be added to
Cargo's bin directory, located at:
/home/pi/.cargo/bin
This path will then be added to your PATH environment variable by
modifying the profile files located at:
/home/pi/.profile
/home/pi/.bashrc
You can uninstall at any time with rustup self uninstall and
these changes will be reverted.
Current installation options:
default host triple: aarch64-unknown-linux-gnu
default toolchain: stable (default)
profile: default
modify PATH variable: yes
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
>1
Rust is installed now. Great!
To get started you may need to restart your current shell.
This would reload your PATH environment variable to include
Cargo's bin directory ($HOME/.cargo/bin).
To configure your current shell, run:
source $HOME/.cargo/env
$ source $HOME/.cargo/env
$ git clone https://github.com/romanz/electrs
$ cd electrs
$ cargo build --locked --no-default-features --release
Finished release [optimized] target(s) in 24m 18s
$ cd
$ pwd
/home/pi
$ sudo su -
$ cp /home/pi/electrs/target/release/electrs /usr/bin/
$ cp /root/electrs/target/release/electrs /usr/bin/
$ systemctl enable electrs
$ systemctl start electrs
$ cd
```
### Step 18: watch initial sync
### Step 31: watch initial sync
> Heads-up: initial sync will likely take more than a day on Raspberry Pi.
> Heads-up: initial sync will likely take more than a day on Raspberry Pi unless node was bootstrapped using bitcoin-dataset.
> Heads-up: run following commands concurrently.
@ -628,15 +890,15 @@ Every 2.0s: bitcoin-cli -datadir=/var/lib/bitcoind getblockchaininfo
{
"chain": "main",
"blocks": 723754,
"headers": 723754,
"bestblockhash": "0000000000000000000652fbe7fc08e12a5880bf3fcba4fea3b075fb1e873eae",
"blocks": 724597,
"headers": 724597,
"bestblockhash": "00000000000000000006913cd13692e0c63a569a5aa1ef869d019de317cca732",
"difficulty": 27967152532434.23,
"mediantime": 1645099367,
"verificationprogress": 0.9999956296623409,
"mediantime": 1645610491,
"verificationprogress": 0.9999997584389468,
"initialblockdownload": false,
"chainwork": "000000000000000000000000000000000000000028e10f1da54a49e1bd77f253",
"size_on_disk": 444503320738,
"chainwork": "00000000000000000000000000000000000000002934d1f8be10aff1a80e6806",
"size_on_disk": 445562831844,
"pruned": false,
"softforks": {
"bip34": {
@ -680,10 +942,18 @@ Every 2.0s: bitcoin-cli -datadir=/var/lib/bitcoind getblockchaininfo
"warnings": ""
}
$ sudo journalctl --follow --unit electrs
Feb 17 07:39:08 raspberrypi electrs[5502]: [2022-02-17T12:39:08.989Z INFO electrs::chain] chain updated: tip=0000000000000000000652fbe7fc08e12a5880bf3fcba4fea3b075fb1e873eae, height=723754
$ journalctl --follow --unit electrs
Feb 23 05:50:49 debian electrs[179948]: [2022-02-23T10:50:49.794Z INFO electrs::chain] chain updated: tip=00000000000000000006913cd13692e0c63a569a5aa1ef869d019de317cca732, height=724597
```
electrs height = bitcoin-cli blocks
bitcoin-cli `"blocks": 724597` = electrs `height=724597`
👍
### Step 31: reboot
```shell
systemctl reboot
```
👍

View File

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
iHUEABYIAB0WIQSceIfhtfy84t/tDhwCxDrQctV3gwUCYh4/2wAKCRACxDrQctV3
gzmNAP9Cce8J/cSi0KeBsZkgVMzvy3pe7ft9EKR/hi77r28tCgD+O88hC1BoqBs+
QVJzH6q1d5xaZQ8TdLMOz3YNdw2bDws=
=CoMy
-----END PGP SIGNATURE-----

View File

@ -2,6 +2,7 @@
Description=Electrs daemon
After=bitcoind.service
Wants=bitcoind.service
[Service]
ExecStart=/usr/bin/electrs --db-dir /var/lib/electrs \
@ -9,13 +10,21 @@ ExecStart=/usr/bin/electrs --db-dir /var/lib/electrs \
--electrum-rpc-addr="127.0.0.1:50001" \
--log-filters INFO
# Process management
####################
Type=simple
Restart=on-failure
TimeoutSec=60
# Directory creation and permissions
####################################
# Run as bitcoin:bitcoin
User=bitcoin
Group=bitcoin
# /var/lib/electrs
StateDirectory=electrs
StateDirectoryMode=0710

View File

@ -1,7 +1,7 @@
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQSceIfhtfy84t/tDhwCxDrQctV3gwUCYg1KOQAKCRACxDrQctV3
g10DAP4ujhjf1DmHNYvJNTPEMsJU495sOiYG6du8gOuMJ8C+JwEA+mirCfw1Ntwq
0hBalye7/whRdtupTbX4aKmMABNQTgU=
=u8ic
iHUEABYKAB0WIQSceIfhtfy84t/tDhwCxDrQctV3gwUCYhvHNgAKCRACxDrQctV3
g6iQAQDhzwb8WHexPWzaeE0oNYpK9KoP6ahLINSGtVyHn7A8vgD/f6BlfR7ub3On
/kkKGnpFwm0PfDhSYR04X1VrhIzqyAA=
=tb8s
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,107 @@
<!--
Title: How to generate bitcoin-dataset
Description: Learn how to generate bitcoin-dataset.
Author: Sun Knudsen <https://github.com/sunknudsen>
Contributors: Sun Knudsen <https://github.com/sunknudsen>
Reviewers:
Publication date: 2022-03-01T17:31:42.392Z
Listed: true
-->
# How to generate bitcoin-dataset
## Requirements
- [Hardened Bitcoin node](../README.md) (with at least 2TB of SSD storage)
- Linux or macOS computer
## Caveats
- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
## Guide
### Step 1: create bitcoin-dataset directory
```console
$ mkdir -p /root/bitcoin-dataset
$ cd /root/bitcoin-dataset
```
### Step 2: create bitcoind and electrs archive
```console
$ tar \
--create \
--directory /var/lib/bitcoind \
--use-compress-program=lz4 \
--verbose \
anchors.dat \
blocks \
chainstate \
fee_estimates.dat \
indexes \
mempool.dat \
peers.dat | \
split \
--bytes 10G \
--numeric-suffixes \
- \
bitcoind.tar.lz4.part
$ tar \
--create \
--directory /var/lib/electrs \
--use-compress-program=lz4 \
--verbose \
. | \
split \
--bytes 10G \
--numeric-suffixes \
- \
electrs.tar.lz4.part
```
### Step 3: create bitcoind and electrs archive checksums
```shell
b3sum \
bitcoind.tar.lz4.part* \
electrs.tar.lz4.part* \
> BLAKE3CHECKSUMS
```
### Step 4: sign checksums
```shell
gpg \
--detach-sig \
--armor \
--output \
BLAKE3CHECKSUMS.asc \
BLAKE3CHECKSUMS
```
### Step 5: create torrent
```console
$ cd
$ transmission-create \
--private \
--tracker https://tracker.sunknudsen.com/announce \
--outfile bitcoin-dataset.torrent \
bitcoin-dataset
```
### Step 6: sign torrent
```shell
gpg \
--detach-sig \
--armor \
--output \
bitcoin-dataset.torrent.asc \
bitcoin-dataset.torrent
```

View File

@ -0,0 +1,240 @@
<!--
Title: How to seed bitcoin-dataset
Description: Learn how to seed bitcoin-dataset.
Author: Sun Knudsen <https://github.com/sunknudsen>
Contributors: Sun Knudsen <https://github.com/sunknudsen>
Reviewers:
Publication date: 2022-03-01T17:31:42.392Z
Listed: true
-->
# How to seed bitcoin-dataset
## Requirements
- [Hardened Debian server](../../how-to-configure-hardened-debian-server/README.md) (with at least 1TB of SSD storage and IPv6 disabled)
- Linux or macOS computer
## Caveats
- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
- When copy/pasting commands that start with `cat << "EOF"`, select all lines at once (from `cat << "EOF"` to `EOF` inclusively) as they are part of the same (single) command
## Guide
### Step 1: install dependencies
```console
$ apt update
$ apt upgrade
$ apt install -y curl gnupg transmission-cli transmission-daemon
$ systemctl disable transmission-daemon
$ systemctl stop transmission-daemon
```
### Step 2: increase `rmem_max` and `wmem_max`
```console
$ cat << "EOF" >> /etc/sysctl.conf
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
EOF
$ sysctl -p
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.core.rmem_max = 4194304
net.core.wmem_max = 1048576
```
### Step 3: configure firewall
> Heads-up: replace `eth0` with network interface (run `ip a` to find interface).
```console
$ NETWORK_INTERFACE=eth0
$ cat << EOF > /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip firewall {
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
iif != "lo" ip daddr 127.0.0.0/8 drop
iifname "$NETWORK_INTERFACE" tcp dport { 22, 51413 } accept
ct state established,related accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
oif "lo" accept
oifname "$NETWORK_INTERFACE" tcp dport { 80, 443, 51413, 57715 } accept
oifname "$NETWORK_INTERFACE" udp dport { 53, 123 } accept
ct state established,related accept
}
}
table ip6 firewall {
chain input {
type filter hook input priority filter; policy drop;
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy drop;
}
}
EOF
$ nft -f /etc/nftables.conf
```
### Step 4: configure transmission-daemon
```shell
cat << "EOF" > /etc/transmission-daemon/settings.json
{
"dht-enabled": false,
"encryption": 2,
"message-level": 1,
"pex-enabled": false,
"port-forwarding-enabled": true,
"rpc-authentication-required": false,
"rpc-enabled": true,
"utp-enabled": false
}
EOF
```
### Step 5: import Suns PGP public key (used to verify downloads below)
```console
$ curl --fail https://sunknudsen.com/sunknudsen.asc | gpg --import
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2070 100 2070 0 0 3219 0 --:--:-- --:--:-- --:--:-- 3214
gpg: key 8C9CA674C47CA060: 1 signature not checked due to a missing key
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 8C9CA674C47CA060: public key "Sun Knudsen <hello@sunknudsen.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: no ultimately trusted keys found
```
imported: 1
👍
### Step 6: verify integrity of Suns PGP public key (learn how [here](../how-to-encrypt-sign-and-decrypt-messages-using-gnupg-on-macos#verify-suns-pgp-public-key-using-fingerprint))
```console
$ gpg --fingerprint hello@sunknudsen.com
pub ed25519 2021-12-28 [C]
E786 274B C92B 47C2 3C1C F44B 8C9C A674 C47C A060
uid [ unknown] Sun Knudsen <hello@sunknudsen.com>
sub ed25519 2021-12-28 [S] [expires: 2022-12-28]
sub cv25519 2021-12-28 [E] [expires: 2022-12-28]
sub ed25519 2021-12-28 [A] [expires: 2022-12-28]
```
Fingerprint matches published fingerprints
👍
### Step 7: download and verify [transmission-daemon.service](./transmission-daemon.service)
```console
$ curl --fail --output /lib/systemd/system/transmission-daemon.service https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/transmission-daemon.service
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1598 100 1598 0 0 568 0 0:00:02 0:00:02 --:--:-- 568
$ curl --fail --output /lib/systemd/system/transmission-daemon.service.asc https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/transmission-daemon.service.asc
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
$ gpg --verify /lib/systemd/system/transmission-daemon.service.asc
gpg: assuming signed data in '/lib/systemd/system/transmission-daemon.service'
gpg: Signature made Sun 27 Feb 2022 01:47:27 PM EST
gpg: using EDDSA key 9C7887E1B5FCBCE2DFED0E1C02C43AD072D57783
gpg: Good signature from "Sun Knudsen <hello@sunknudsen.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: E786 274B C92B 47C2 3C1C F44B 8C9C A674 C47C A060
Subkey fingerprint: 9C78 87E1 B5FC BCE2 DFED 0E1C 02C4 3AD0 72D5 7783
```
Good signature
👍
### Step 8: download and verify bitcoin-dataset torrent
```console
$ curl --fail --remote-name https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/bitcoin-dataset.torrent
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4271k 100 4271k 0 0 3911k 0 0:00:01 0:00:01 --:--:-- 3911k
$ curl --fail --remote-name https://raw.githubusercontent.com/sunknudsen/privacy-guides/master/how-to-self-host-hardened-bitcoin-node/bitcoin-dataset.torrent.asc
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 228 100 228 0 0 740 0 --:--:-- --:--:-- --:--:-- 740
$ gpg --verify bitcoin-dataset.torrent.asc
gpg: assuming signed data in 'bitcoin-dataset.torrent'
gpg: Signature made Tue 01 Mar 2022 10:46:35 AM EST
gpg: using EDDSA key 9C7887E1B5FCBCE2DFED0E1C02C43AD072D57783
gpg: Good signature from "Sun Knudsen <hello@sunknudsen.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: E786 274B C92B 47C2 3C1C F44B 8C9C A674 C47C A060
Subkey fingerprint: 9C78 87E1 B5FC BCE2 DFED 0E1C 02C4 3AD0 72D5 7783
```
Good signature
👍
### Step 9: enable and start transmission-daemon
```console
$ systemctl enable transmission-daemon
$ systemctl start transmission-daemon
```
### Step 10: start bitcoin-dataset torrent
```console
$ transmission-remote --add bitcoin-dataset.torrent --start
```
### Step 11: watch bitcoin-dataset torrent
```console
$ watch transmission-remote --list
Every 2.0s: transmission-remote --list debian: Tue Mar 1 11:56:05 2022
ID Done Have ETA Up Down Ratio Status Name
1 100% 458.4 GB Done 0.0 0.0 0.0 Idle bitcoin-dataset
Sum: 458.4 GB 0.0 0.0
```
100%
👍

View File

@ -0,0 +1,66 @@
[Unit]
Description=Transmission daemon
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/bin/transmission-daemon \
--config-dir /etc/transmission-daemon \
--download-dir /var/lib/transmission-daemon/downloads \
--encryption-required \
--foreground
ExecStop=/bin/kill -s STOP $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID
# Make sure the config directory is readable by the service user
PermissionsStartOnly=true
ExecStartPre=/bin/chgrp debian-transmission /etc/transmission-daemon
# Process management
####################
Type=notify
Restart=on-failure
TimeoutSec=60
# Directory creation and permissions
####################################
# Run as debian-transmission:debian-transmission
User=debian-transmission
Group=debian-transmission
# /etc/transmission-daemon
ConfigurationDirectory=transmission-daemon
ConfigurationDirectoryMode=0710
# /var/lib/transmission-daemon
StateDirectory=transmission-daemon
StateDirectoryMode=0710
# Hardening measures
####################
# Provide a private /tmp and /var/tmp.
PrivateTmp=true
# Mount /usr, /boot/ and /etc read-only for the process.
ProtectSystem=full
# Deny access to /home, /root and /run/user
ProtectHome=true
# Disallow the process and all of its children to gain
# new privileges through execve().
NoNewPrivileges=true
# Use a new /dev namespace only populated with API pseudo devices
# such as /dev/null, /dev/zero and /dev/random.
PrivateDevices=true
# Deny the creation of writable and executable memory mappings.
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQSceIfhtfy84t/tDhwCxDrQctV3gwUCYhvHPwAKCRACxDrQctV3
gzhmAP9K9DvLA5T3fA6oiLhrD/wxuushmWXtG4OQg7OLt04XzwEAl+5+6COvGZIh
RQO7+mdgPFfQ0eYP3tVCDVqfgSkfjgs=
=l1uP
-----END PGP SIGNATURE-----