Setup a Debian instance called "bitcoind" with the following ports allowed in the firewall:
- 8332 (Bitcoin RPC)
- 8333/18333/38333/18444 (Bitcoin Mainnet/Testnet/Signet/Regtest)
- 29000 (ZeroMQ block hash publisher)
- 29001 (ZeroMQ transaction publisher)
- 29002 (ZeroMQ block publisher)
Place the bitcoind and bitcoin-cli binaries into /usr/bin/ and make the binaries executable.
Create a system user called "bitcoin" without a home directory and without a shell.
root@bitcoind:~$ useradd --system --no-create-home --home /nonexistent --shell /usr/sbin/nologin bitcoinPut the following contents into the /etc/bitcoin/bitcoin.conf file:
mainnet=1
[mainnet]
server=1
txindex=1
disablewallet=0
rpcuser=user
rpcpassword=password
rpcallowip=0.0.0.0/0
rpcbind=0.0.0.0:8332
zmqpubhashblock=tcp://0.0.0.0:29000
zmqpubrawtx=tcp://0.0.0.0:29001
zmqpubrawblock=tcp://0.0.0.0:29002
listen=1Change each occurrence of mainnet to the network which this should run on.
Adjust the ownership and permissions of the config file and directory.
root@bitcoind:~$ chmod 0710 /etc/bitcoin
root@bitcoind:~$ chmod 0640 /etc/bitcoin/bitcoin.conf
root@bitcoind:~$ chown -R bitcoin:bitcoin /etc/bitcoinSetup a systemd service for bitcoind by putting the following contents into the /usr/lib/systemd/system/bitcoind.service file:
[Unit]
Description=Bitcoin daemon
After=network-online.target
Wants=network-online.target
[Service]
Environment='MALLOC_ARENA_MAX=1'
ExecStart=/usr/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf \
-datadir=/var/lib/bitcoind \
-startupnotify='systemd-notify --ready' \
-shutdownnotify='systemd-notify --stopping'
Type=notify
NotifyAccess=all
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
User=bitcoin
Group=bitcoin
# /run/bitcoind
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
# /etc/bitcoin
ConfigurationDirectory=bitcoin
ConfigurationDirectoryMode=0710
# /var/lib/bitcoind
StateDirectory=bitcoind
StateDirectoryMode=0710
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.targetUpdate the running systemd configuration.
root@bitcoind:~$ systemctl daemon-reloadStart bitcoind.
root@bitcoind:~$ systemctl start bitcoind.serviceEnable the bitcoind.service so it automatically starts up when the instance is started.
root@bitcoind:~$ systemctl enable bitcoind.serviceTo be able to use bitcoin-cli without having to manually specify -rpcuser and -rpcpassword, put the following contents into ~/.bitcoin/bitcoin.conf:
rpcuser=user
rpcpassword=password
Create a wallet (the name does not matter) that will be loaded on startup.
root@bitcoind:~$ bitcoin-cli -named createwallet wallet_name=main load_on_startup=trueGenerate 101 blocks with the reward going to the created wallet.
root@bitcoind:~$ bitcoin-cli -generate 101The wallet should now have a balance of 50 BTC
root@bitcoind:~$ bitcoin-cli getbalanceInstall openssl on a local system if not already installed.
root@local:~$ apt install opensslThis tool is going to be used to generate TLS certificates.
First initialize a certificate authority.
user@local:~$ openssl req -x509 -noenc -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout ca.key -out ca.crt -days 3650 -subj "/CN=lndetcd-ca"Generate the certificates for the etcd nodes.
Perform the following steps for each etcd node:
user@local:~$ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout etcd1.key -out etcd1.csr -noenc -subj "/CN=etcd1" -addext "subjectAltName=IP:${IP_OF_LNDETCD1},IP:127.0.0.1"
user@local:~$ openssl req -x509 -in etcd1.csr -CA ca.crt -CAkey ca.key -out etcd1.crt -days 3650 -copy_extensions copyLastly generate a client certificate.
user@local:~$ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout client.key -out client.csr -noenc -subj "/CN=client"
user@local:~$ openssl req -x509 -in client.csr -CA ca.crt -CAkey ca.key -out client.crt -days 3650 -copy_extensions copyIf a PostgreSQL database is planned, also generate TLS certificates for Patroni.
Perform the following steps for each Patroni instance:
user@local:~$ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout patroni1.key -out patroni1.csr -noenc -subj "/CN=patroni1" -addext "subjectAltName=IP:${IP_OF_LNDETCDPG1},IP:127.0.0.1"
user@local:~$ openssl req -x509 -in patroni1.csr -CA ca.crt -CAkey ca.key -out patroni1.crt -days 3650 -copy_extensions copyAlso generate a client certificate for Patroni.
user@local:~$ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -keyout patroniclient.key -out patroniclient.csr -noenc -subj "/CN=patroniclient"
user@local:~$ openssl req -x509 -in patroniclient.csr -CA ca.crt -CAkey ca.key -out patroniclient.crt -days 3650 -copy_extensions copySetup three Debian instances with ECC memory called "lndetcd1", "lndetcd2" and "lndetcd3" with the following ports allowed in the firewall on each of them:
- 2379 (etcd client communication)
- 2380 (etcd peer communication)
- 9735 (Lightning)
If a PostgreSQL database is planned, also allow the following ports:
- 5432 (PostgreSQL)
- 8008 (Patroni REST API)
Create a system user called "bitcoin" with a home directory and set a password on each instance.
root@lndetcdx:~$ useradd --system --create-home --shell /bin/bash bitcoin
root@lndetcdx:~$ passwd bitcoinInstall etcd and etcdctl on all three instances.
root@lndetcdx:~$ apt update
root@lndetcdx:~$ apt install etcd-server etcd-clientSince the etcd.service is started automatically during installation, stop it for now and delete the data directory of etcd on every instance to start fresh.
root@lndetcdx:~$ systemctl stop etcd.service
root@lndetcdx:~$ rm -r /var/lib/etcd/defaultTo ensure that the lnd.service does not fail to start because of a dependency problem when the etcd.service times out during startup, configure RestartMode=direct on the etcd.service. This RestartMode=direct was only introduced in systemd 254, so systemd has to be upgraded to that version.
Start with adding the bookworm-backports repository to apt, by adding the following line to /etc/apt/sources.list on each instance:
deb http://deb.debian.org/debian bookworm-backports main
Then update the package lists on each instance.
root@lndetcdx:~$ apt updateAnd install systemd 254 from the bookworm-backports repository on each instance.
root@lndetcdx:~$ apt install systemd/stable-backportsWith systemd upgraded, add RestartMode=direct to the [Service] section of the /usr/lib/systemd/system/etcd.service file on each instance.
Finally update the running systemd configuration on each instance.
root@lndetcdx:~$ systemctl daemon-reloadCreate a directory at /etc/etcd on all three instances.
root@lndetcdx:~$ mkdir /etc/etcdCopy ca.crt, etcd1.crt, etcd1.key, client.crt and client.key from the local system into /etc/etcd on "lndetcd1", "lndetcd2" and "lndetcd3".
Restrict the access rights of the certificates and keys to only the etcd user and group.
root@lndetcdx:~$ chown etcd:etcd /etc/etcd/*
root@lndetcdx:~$ chmod 400 /etc/etcd/etcd1.key /etc/etcd/etcd1.crt
root@lndetcdx:~$ chmod 440 /etc/etcd/ca.crt /etc/etcd/client.crt /etc/etcd/client.keyAdd the bitcoin user to the etcd group, to allow lnd to access the etcd client certificate and key.
root@lndetcdx:~$ /sbin/usermod -a -G etcd bitcoinPut the following contents into the /etc/default/etcd file:
ETCD_NAME=etcd1
ETCD_INITIAL_CLUSTER="etcd1=https://${IP_OF_LNDETCD1}:2380,etcd2=https://${IP_OF_LNDETCD2}:2380,etcd3=https://${IP_OF_LNDETCD3}:2380"
ETCD_ADVERTISE_CLIENT_URLS=https://${OWN_IP}:2379
ETCD_LISTEN_CLIENT_URLS=https://0.0.0.0:2379
ETCD_LISTEN_PEER_URLS=https://0.0.0.0:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://${OWN_IP}:2380
ETCD_MAX_TXN_OPS=16384
ETCD_CERT_FILE=/etc/etcd/etcd1.crt
ETCD_KEY_FILE=/etc/etcd/etcd1.key
ETCD_TRUSTED_CA_FILE=/etc/etcd/ca.crt
ETCD_PEER_CERT_FILE=/etc/etcd/etcd1.crt
ETCD_PEER_KEY_FILE=/etc/etcd/etcd1.key
ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/ca.crt
ETCD_PEER_CLIENT_CERT_AUTH=true
ETCD_CLIENT_CERT_AUTH=true
Repeat that for "lndetcd2" and "lndetcd3" with ETCD_NAME, $OWN_IP and the certificate files changed respectively.
Then start etcd on each instance.
root@lndetcdx:~$ systemctl start etcd.serviceThen list the members of the cluster on any of the instances and make sure that all members are listed.
root@lndetcdx:~$ export ETCDCTL_CACERT=/etc/etcd/ca.crt
root@lndetcdx:~$ export ETCDCTL_CERT=/etc/etcd/client.crt
root@lndetcdx:~$ export ETCDCTL_KEY=/etc/etcd/client.key
root@lndetcdx:~$ etcdctl member list --write-out=tableCheck whether the cluster is healthy.
root@lndetcdx:~$ etcdctl endpoint health --clusterCheck the status of each endpoint in the cluster.
root@lndetcdx:~$ etcdctl endpoint status --cluster --write-out=tableEnable the etcd.service on each instance so it automatically starts up when the instance is started.
root@lndetcdx:~$ systemctl enable etcd.serviceSkip this step if a PostgreSQL database is not planned.
Start by installing PostgreSQL and Patroni on all three instances.
root@lndetcdpgx:~$ apt install postgresql patroniStop the postgresql.service and the patroni.service which might have been started automatically during installation, and delete the PostgreSQL data directory on each instance to start fresh.
root@lndetcdpgx:~$ systemctl stop postgresql.service
root@lndetcdpgx:~$ systemctl stop 'postgresql@*.service'
root@lndetcdpgx:~$ systemctl stop patroni.service
root@lndetcdpgx:~$ rm -r /var/lib/postgresql/15/mainSince PostgreSQL is not intended to be started by systemd, but will instead be started by Patroni, disable and mask the postgresql.service so that it cannot be started directly by systemd.
root@lndetcdpgx:~$ systemctl disable postgresql.service
root@lndetcdpgx:~$ systemctl disable postgresql@.service
root@lndetcdpgx:~$ systemctl mask postgresql.service
root@lndetcdpgx:~$ systemctl mask postgresql@.serviceCopy patroni1.crt, patroni1.key, patroniclient.crt and patroniclient.key from the local system into /etc/patroni on "lndetcdpg1", "lndetcdpg2" and "lndetcdpg3". Rename patroniclient.crt and patroniclient.key to client.crt and client.key.
Restrict access to the certificates and keys to the postgres user and group only.
root@lndetcdpgx:~$ chown postgres:postgres /etc/patroni/patroni1.crt /etc/patroni/patroni1.key /etc/patroni/client.crt /etc/patroni/client.key
root@lndetcdpgx:~$ chmod 400 /etc/patroni/patroni1.crt /etc/patroni/patroni1.key /etc/patroni/client.crt /etc/patroni/client.keyPut the following contents into the /etc/patroni/config.yml file:
name: postgres1
scope: postgres
etcd3:
protocol: https
hosts:
- ${LNDETCDPG1_IP}:2379
- ${LNDETCDPG2_IP}:2379
- ${LNDETCDPG3_IP}:2379
cacert: /etc/etcd/ca.crt
cert: /etc/etcd/client.crt
key: /etc/etcd/client.key
restapi:
listen: 0.0.0.0:8008
connect_address: ${OWN_IP}:8008
certfile: /etc/patroni/patroni1.crt
keyfile: /etc/patroni/patroni1.key
cafile: /etc/etcd/ca.crt
verify_client: required
ctl:
certfile: /etc/patroni/client.crt
keyfile: /etc/patroni/client.key
bootstrap:
dcs:
maximum_lag_on_failover: 1048576
synchronous_mode: true
postgresql:
use_pg_rewind: true
parameters:
wal_level: replica
synchronous_commit: remote_apply
max_wal_senders: 10
synchronous_standby_names: '*'
hot_standby: on
pg_hba:
- local all all peer
- host all all 127.0.0.1/32 md5
- host all all ::1/128 md5
- host all all ${IP_NETWORK}/${NETWORK_BITS} md5
- local replication all peer
- host replication all 127.0.0.1/32 md5
- host replication all ::1/128 md5
- host replication all ${IP_NETWORK}/${NETWORK_BITS} md5
post_init: /etc/patroni/post_init.sh
postgresql:
authentication:
superuser:
username: postgres
password: POSTGRES_SUPERUSER_PASSWORD
replication:
username: replicator
password: POSTGRES_REPLICATION_PASSWORD
rewind:
username: rewinder
password: POSTGRES_REWIND_PASSWORD
listen: '*:5432'
connect_address: ${OWN_IP}:5432
data_dir: /var/lib/postgresql/15/main
bin_dir: /usr/lib/postgresql/15/bin
config_dir: /etc/postgresql/15/main
pgpass: /var/lib/postgresql/15-main.pgpassRepeat that for "lndetcdpg2" and "lndetcdpg3" with name, $OWN_IP and the certificate files changed respectively.
Restrict access to /etc/patroni/config.yml to the postgres user only.
root@lndetcdpgx:~$ chown postgres:postgres /etc/patroni/config.yml
root@lndetcdpgx:~$ chmod 400 /etc/patroni/config.ymlPut the following contents into the /etc/patroni/post_init.sh file:
#!/bin/sh
createuser lnd
psql <<EOF
ALTER USER lnd WITH PASSWORD 'POSTGRES_LND_PASSWORD';
EOF
createdb -O lnd lndMake the file executable only by the postgres user.
root@lndetcdpgx:~$ chown postgres:postgres /etc/patroni/post_init.sh
root@lndetcdpgx:~$ chmod 500 /etc/patroni/post_init.shFinally, add the postgres user to the etcd group so that it can access the etcd client certificate and key.
root@lndetcdpgx:~$ /sbin/usermod -a -G etcd postgresThen start Patroni on each instance.
root@lndetcdpgx:~$ systemctl start patroni.serviceList the members of the Patroni cluster and make sure that all three members are listed. There should be exactly one "Leader", one "Sync Standby", and one "Replica". The result should look something like this:
root@lndetcdpgx:~$ patronictl -c /etc/patroni/config.yml list
+ Cluster: postgres ----------+--------------+---------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-----------+-----------------+--------------+---------+----+-----------+
| postgres1 | 192.168.122.101 | Sync Standby | running | 1 | 0 |
| postgres2 | 192.168.122.102 | Leader | running | 1 | |
| postgres3 | 192.168.122.103 | Replica | running | 1 | 0 |
+-----------+-----------------+--------------+---------+----+-----------+Enable the patroni.service on each instance so that it starts automatically when the instance is started.
root@lndetcdpgx:~$ systemctl enable patroni.serviceInstall tor on each instance.
root@lndetcdx:~$ apt install torReplace the contents of the /etc/tor/torrc file with the following on each instance:
ExitPolicy reject *:*
SOCKSPort 9050
ControlPort 9051
CookieAuthentication 1
Restart tor to apply the new configuration
root@lndetcdx:~$ systemctl restart tor.serviceAdd the bitcoin user to the debian-tor group on each instance.
root@lndetcdx:~$ /sbin/usermod -a -G debian-tor bitcoinPlace the lnd and lncli binaries into /usr/bin/ on each instance and make the binaries executable. Make sure that lnd is at least on version v0.18.3-beta or that it at least has the following patch applied: lightningnetwork/lnd#8938 Also make sure that lnd was compiled with the "kvdb_etcd" build tag.
Put the following contents into the /home/bitcoin/.lnd/lnd.conf file on each instance but change the cluster.id accordingly:
[Application Options]
listen=0.0.0.0:9735
alias=lndetcd
[Bitcoin]
bitcoin.regtest=true
bitcoin.node=bitcoind
[Bitcoind]
bitcoind.rpcuser=user
bitcoind.rpcpass=password
bitcoind.rpchost=${IP_OF_BITCOIND}:8332
bitcoind.zmqpubrawtx=tcp://${IP_OF_BITCOIND}:29001
bitcoind.zmqpubrawblock=tcp://${IP_OF_BITCOIND}:29002
bitcoind.estimatemode=ECONOMICAL
[tor]
tor.active=true
tor.v3=true
tor.skip-proxy-for-clearnet-targets=true
[wtclient]
wtclient.active=true
[healthcheck]
healthcheck.leader.interval=60s
[db]
db.backend=etcd
[etcd]
db.etcd.host=127.0.0.1:2379
db.etcd.cert_file=/etc/etcd/client.crt
db.etcd.key_file=/etc/etcd/client.key
db.etcd.insecure_skip_verify=1
[cluster]
cluster.enable-leader-election=1
cluster.leader-elector=etcd
cluster.etcd-election-prefix=cluster-leader
cluster.id=lndetcd1
cluster.leader-session-ttl=100If a PostgreSQL setup is planned, put the following in the [db] section instead:
db.backend=postgres
db.postgres.dsn=postgresql://lnd:POSTGRES_LND_PASSWORD@127.0.0.1:5432/lnd
db.postgres.timeout=0
db.use-native-sql=trueMake sure that the bitcoin user and bitcoin group own the /home/bitcoin/.lnd directory on each instance.
root@lndetcdx:~$ chown -R bitcoin:bitcoin /home/bitcoin/.lndSetup a systemd service for lnd on each instance by putting the following contents into /usr/lib/systemd/system/lnd.service:
[Unit]
Description=LND Lightning Daemon
After=etcd.service
BindsTo=etcd.service
After=tor.service
Wants=tor.service
[Service]
ExecStart=/usr/bin/lnd
User=bitcoin
Group=bitcoin
Restart=always
RestartSec=30
Type=notify
TimeoutStartSec=infinity
TimeoutStopSec=1800
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.targetIf a PostgreSQL setup is planned, add the following to the [Unit] section:
After=patroni.service
BindsTo=patroni.serviceUpdate the running systemd configuration on each instance.
root@lndetcdx:~$ systemctl daemon-reloadStart LND on only one instance. If a PostgreSQL setup is planned, the choice of the instance cannot be arbitrary. LND has to be started on the instance of the PostgreSQL primary. The primary can be found with patronictl -c /etc/patroni/config.yml list.
root@lndetcdx:~$ systemctl start lnd.serviceSwitch to the bitcoin user and create a wallet.
root@lndetcdx:~$ su bitcoin
bitcoin@lndetcdx:~$ lncli create
bitcoin@lndetcdx:~$ exitOnce the wallet is created, create a file at /home/bitcoin/lnd_pwd containing the wallet unlock password on each instance while making sure that only the bitcoin user and bitcoin group have access to that file.
root@lndetcdx:~$ echo $(read -sp "Password: ";echo $REPLY) > /home/bitcoin/lnd_pwd
root@lndetcdx:~$ chown bitcoin:bitcoin /home/bitcoin/lnd_pwd
root@lndetcdx:~$ chmod 660 /home/bitcoin/lnd_pwdThen add the following line to the [Application Options] section in /home/bitcoin/.lnd/lnd.conf on each instance:
wallet-unlock-password-file=/home/bitcoin/lnd_pwd
Copy /home/bitcoin/.lnd/v3_onion_private_key to the other instances that do not have lnd running yet. This ensures that all nodes in the cluster will be reachable via the same onion hostname. Keep in mind though, that during failover it can take up to 10 minutes for the new leader node to be accessible through the tor hidden service.
Now start lnd on the other instances that do not have lnd running yet.
root@lndetcdx:~$ systemctl start lnd.serviceThe lnd services should now have a message similar to this in their log output:
LTND: Starting leadership campaign (lndetcd2)
Enable the service on each instance, to make sure that lnd is started automatically.
root@lndetcdx:~$ systemctl enable lnd.serviceTo make the active leader always accessible via the same IP address, use a floating IP address that is always assigned to the currently active leader.
Create an sh script with the following contents at /usr/local/bin/lnd-floating-ip.sh on each instance:
#!/bin/sh
FLOATING_IP="192.168.0.100" # Replace this
SUBNET_MASK="24" # Replace this
INTERFACE="eth0" # Replace this
while true; do
sleep 20
lncli --lnddir /home/bitcoin/.lnd state | grep -q -E 'NON_EXISTING|LOCKED|UNLOCKED|RPC_ACTIVE|SERVER_ACTIVE'
IS_LEADER=$?
ip addr show $INTERFACE | grep -q $FLOATING_IP
IP_ASSIGNED=$?
if [ $IS_LEADER -eq 0 ] && [ $IP_ASSIGNED -ne 0 ]; then
echo "Assigning the floating IP address to this node since it is the leader"
ip addr add $FLOATING_IP/$SUBNET_MASK dev $INTERFACE
arping -c 1 -I $INTERFACE $FLOATING_IP
elif [ $IS_LEADER -ne 0 ] && [ $IP_ASSIGNED -eq 0 ]; then
echo "Removing the floating IP address since this node is no longer the leader"
ip addr del $FLOATING_IP/$SUBNET_MASK dev $INTERFACE
fi
doneSet FLOATING_IP to the floating IP address to use for the active LND leader node. Set INTERFACE to the network interface that the floating IP address should be assigned to. (Can be the same interface as for the regular IP address of the instance) Set SUBNET_MASK to the subnet mask of INTERFACE.
Make the script executable:
root@lndetcdx:~$ chmod +x /usr/local/bin/lnd-floating-ip.shIn order for the script to work, install arping on all instances:
root@lndetcdx:~$ apt install arpingSetup a systemd service for lnd-floating-ip on each instance by putting the following contents into /usr/lib/systemd/system/lnd-floating-ip.service:
[Unit]
Description=LND Floating IP
After=lnd.service
Wants=lnd.service
[Service]
ExecStart=/usr/local/bin/lnd-floating-ip.sh
Restart=always
Type=exec
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.targetUpdate the running systemd configuration on each instance.
root@lndetcdx:~$ systemctl daemon-reloadStart and enable lnd-floating-ip on all instances.
root@lndetcdx:~$ systemctl start lnd-floating-ip.service
root@lndetcdx:~$ systemctl enable lnd-floating-ip.serviceTo check whether the lnd cluster works properly, stop the currently active lnd node and another node in the cluster should automatically take over.
Another test one can do is to disconnect one of the lnd nodes from the network. The disconnected node should automatically resign from the leader role and a different node should take over.
Setup a Debian instance called "lndwt" on an offsite location with the following ports allowed in the firewall:
- 8333/18333/38333/18444 (Bitcoin Mainnet/Testnet/Signet/Regtest)
- 9911 (LND watchtower)
Place the bitcoind, bitcoin-cli, lnd and lncli binaries into /usr/bin/ and make them executable. Make sure that these lnd and lncli binaries where compiled with the "watchtowerrpc" build tag.
Create a system user called "bitcoin" with a home directory and set a password.
root@lndwt:~$ useradd --system --create-home --shell /bin/bash bitcoin
root@lndwt:~$ passwd bitcoinPut the following contents into the /etc/bitcoin/bitcoin.conf file:
regtest=1
[regtest]
server=1
prune=8064
disablewallet=1
rpcallowip=127.0.0.1
rpcbind=127.0.0.1:8332
zmqpubrawtx=tcp://127.0.0.1:29001
zmqpubrawblock=tcp://127.0.0.1:29002
listen=1This will configure a pruned bitcoind node. A watchtower does not need a full node.
Adjust the ownership and permissions of the config file and directory.
root@lndwt:~$ chmod 0710 /etc/bitcoin
root@lndwt:~$ chmod 0640 /etc/bitcoin/bitcoin.conf
root@lndwt:~$ chown -R bitcoin:bitcoin /etc/bitcoinSetup a systemd service for bitcoind by putting the following contents into the /usr/lib/systemd/system/bitcoind.service file:
[Unit]
Description=Bitcoin daemon
After=network-online.target
Wants=network-online.target
[Service]
Environment='MALLOC_ARENA_MAX=1'
ExecStart=/usr/bin/bitcoind -pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf \
-datadir=/var/lib/bitcoind \
-startupnotify='systemd-notify --ready' \
-shutdownnotify='systemd-notify --stopping'
Type=notify
NotifyAccess=all
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
TimeoutStartSec=infinity
TimeoutStopSec=600
User=bitcoin
Group=bitcoin
# /run/bitcoind
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
# /etc/bitcoin
ConfigurationDirectory=bitcoin
ConfigurationDirectoryMode=0710
# /var/lib/bitcoind
StateDirectory=bitcoind
StateDirectoryMode=0710
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
SystemCallArchitectures=native
[Install]
WantedBy=multi-user.targetPut the following contents into the /home/bitcoin/.lnd/lnd.conf file:
[Application Options]
[Bitcoin]
bitcoin.regtest=true
bitcoin.node=bitcoind
[Bitcoind]
bitcoind.rpchost=127.0.0.1:8332
bitcoind.rpccookie=/var/lib/bitcoind/regtest/.cookie
bitcoind.zmqpubrawtx=tcp://127.0.0.1:29001
bitcoind.zmqpubrawblock=tcp://127.0.0.1:29002
bitcoind.estimatemode=ECONOMICAL
[watchtower]
watchtower.active=true
watchtower.listen=0.0.0.0:9911Make the .lnd directory owned by the bitcoin user and group.
root@lndwt:~$ chown -R bitcoin:bitcoin /home/bitcoin/.lndSetup a systemd service for lnd by putting the following contents into /usr/lib/systemd/system/lnd.service:
[Unit]
Description=LND Lightning Daemon
After=bitcoind.service
Wants=bitcoind.service
[Service]
ExecStart=/usr/bin/lnd
User=bitcoin
Group=bitcoin
Restart=always
RestartSec=30
Type=notify
TimeoutStartSec=infinity
TimeoutStopSec=1800
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.targetUpdate the running systemd configuration.
root@lndwt:~$ systemctl daemon-reloadStart bitcoind & lnd.
root@lndwt:~$ systemctl start bitcoind.service
root@lndwt:~$ systemctl start lnd.serviceEnable the bitcoind.service & lnd.service so they automatically start up when the instance is started.
root@lndwt:~$ systemctl enable bitcoind.service
root@lndwt:~$ systemctl enable lnd.serviceSwitch to the bitcoin user.
root@lndwt:~$ su bitcoinCreate a file at /home/bitcoin/.bitcoin/bitcoin.conf containing the path to the bitcoind RPC cookie file:
rpccookiefile=/var/lib/bitcoind/regtest/.cookie
If this is running on regtest, add the first bitcoin node as a peer, so that they are synced together. (Not necessary on mainnet, testnet or signet)
bitcoin@lndwt:~$ bitcoin-cli addnode ${IP_OF_FIRST_BITCOIND_NODE} addCreate an lnd wallet. This wallet will not serve any purpose and is only needed because lnd expects a wallet to exist. So there is no need to backup this wallet and the password does not have to be strong.
bitcoin@lndwt:~$ lncli createOnce the wallet is created, create a file at /home/bitcoin/lnd_pwd containing the wallet unlock password.
Then add the following line to the [Application Options] section in /home/bitcoin/.lnd/lnd.conf:
wallet-unlock-password-file=/home/bitcoin/lnd_pwd
Get the public key of the watchtower.
bitcoin@lndwt:~$ lncli tower infoThis returns a JSON response. The public key can be found under the "pubkey" key.
Add the watchtower to the watchtower client of the currently active lnd node in the cluster. This change will automatically replicate to all other nodes in the cluster.
bitcoin@lndetcdx:~$ lncli wtclient add ${WATCHTOWER_PUBKEY}@${WATCHTOWER_IP}:9911Check that the watchtower is added and that "active_session_candidate" is true.
bitcoin@lndetcdx:~$ lncli wtclient towers