Manual Deployment Extended

This document lists steps for manually deploying BTCPay Server and additional related components. Following these steps is likely to take a long time. A shorter and more pragmatic approach is to use a docker based deployment.

Manual installation is NOT recommended for production use unless you are very confident with your Operating System and Bitcoin security expertise. If you are unsure use the docker deployment or one of the other deployment options.

Installation Steps Overview

The instructions in this article have been tested on Ubuntu 18.04. They should be applicable to other Linux based distributions. They are also based on all components being on the same host or virtual machine. It is possible to split the components across different hosts but these instructions don't describe that.

An example hostname of mainnet.demo.btcpayserver.org has been used in certain places in these instructions. It needs to be replaced with the hostname you are using for your BTCPay Server.

Security

If you do use these instructions to install a BTCPay Server connected to the Bitcoin mainnet then at a minimum you should understand how the wallet mechanisms work. It's highly recommended to read the two articles below and ask questions if anything is not clear.

As an additional aid below is a lit of iptables rules and instructions which should include all the ports that need to be open. NO WARRANTY. Use at your own risk, including risk of locking yourself out.

~$ vi iptables.txt
# Generated by iptables-save v1.6.1 on Mon May 27 18:48:11 2019
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8333 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 9375 -j ACCEPT
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
COMMIT
# Completed on Mon May 27 18:48:11 2019
~$ sudo iptables-restore < iptables.txt

At this point if you are still connected to you ssh session it's a good sign. If not the rules are temporary and you can use whatever mechanism you have to remotely reboot your server and try again.

The rules have now been temporarily applied. To apply the rules automatically each time your server starts use the iptables-persistent package.

~$ sudo apt install iptables-persistent

If you subsequently change the iptables rules and want to save them across reboots use the command below.

~$ sudo netfilter-persistent save

Unprivileged user

These instructions configure everything to run under an unprivileged user called admin. Create this user before proceeding:

~$ sudo useradd -m -s /dev/null admin

Prerequisites

  • Postgresql

  • Tor

  • NGINX and Let's Encrypt

Application Components

  • Bitcoin Daemon1

  • NBXplorer1,2

  • BTCPay Server1,2

  • Lightning Network Daemon (lnd)2

  • Ride The Lightning (RTL)2

1 The bare minimum install of a BTCPay server only requires these items. Using a bare minimum configuration reduces the functionality: no lightning payments, no auto-renewal of TLS certificates, less reliable data store, less capable of handling NAT and more.

2 Built from source code (note if you'd like to build the Bitcoin Daemon from source the instruction are here).

Postgresql

Postgresql can be used by BTCPay Server in place of the default SQLite file based storage. It's also possible to use MySQL.

🚚 Install

~$ sudo apt install postgresql postgresql-contrib

✒️ Configuration

Covered in BTCPay Server Configuration.

👍 Check

~$ psql --version
psql (PostgreSQL) 10.8 (Ubuntu 10.8-0ubuntu0.18.04.1)
~$ sudo systemctl status postgresql
~$ sudo -u postgres psql
psql (10.8 (Ubuntu 10.8-0ubuntu0.18.04.1))
Type "help" for help.
postgres=# \q

Tor

Tor can be used by the following components to provide enhanced privacy and/or help with NAT traversal:

  • Bitcoin-core Daemon

  • Lightning Network Daemon (lnd).

🚚 Install

~$ sudo apt install apt-transport-https
~$ sudo vi /etc/apt/sources.list # (and append two lines below)
deb https://deb.torproject.org/torproject.org bionic main
deb-src https://deb.torproject.org/torproject.org bionic main
~$ curl https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --import
~$ gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -
~$ sudo apt update
~$ sudo apt install tor deb.torproject.org-keyring

✒️ Configuration

~$ sudo vi /etc/tor/torrc # (and uncomment two lines below)
ControlPort 9051
CookieAuthentication 1
~$ sudo systemctl restart tor

Covered further in Bitcoin and Lightning Network Daemon sections.

👍 Check

~$ netstat -tlnp | grep tor # (lines below correspond to the tor control port and SOCKS proxy)
tcp 0 0 127.0.0.1:9050 0.0.0.0:* LISTEN 1376/tor
tcp 0 0 127.0.0.1:9051 0.0.0.0:* LISTEN 1376/tor

NGINX and Let's Encrypt

NGINX is used as a web server to manage HTTP requests to BTCPay Server and Ride The Lightning. Paired with Let's Encrypt it allows seamless procurement and renewal of a TLS certificate for your BTCPay Server instance.

Let's Encrypt is a free service for procuring and renewing TLS certificates. The service comes with scripts that can be installed to automatically manage the whole process.

🚚 Install

1. Install NGINX.

~$ sudo apt install nginx

2. Install Let's Encrypt

~$ sudo add-apt-repository ppa:certbot/certbot
~$ sudo apt update
~$ sudo apt install certbot python-certbot-nginx

✒️ Configuration

1. Let's Encrypt TLS certificate.

You must create an A or AAAA record for \ that points to the IP address of your server instance. If your server is behind NAT then you need to forward port 80 to your instance.

The certbot script works by checking for a specific file on the web server hosting the requested domain. If it can't get the file the TLS certificate won't be issued. If the initial attempt fails it will be periodically re-attempted or you can simply re-run the command.

sudo certbot --nginx -d <your domain name> # (e.g: sudo certbot --nginx -d mainnet.demo.btcpayserver.org)

2. Add NGINX configuration file.

The configuration file below has been copied from the BTCPay Server docker install.

Search for "mainnet.demo.btcpayserver.org" and replace it with your own domain name.

~$ vi default.conf
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Prevent Nginx Information Disclosure
server_tokens off;
# Default dhparam
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
default off;
https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log off;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
client_header_buffer_size 500k;
large_client_header_buffers 4 500k;
http2_max_field_size 500k;
http2_max_header_size 500k;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
server_name mainnet.demo.btcpayserver.org;
listen 80 ;
access_log /var/log/nginx/access.log vhost;
return 301 https://$host$request_uri;
}
server {
client_max_body_size 100M;
server_name mainnet.demo.btcpayserver.org;
listen 443 ssl http2 ;
access_log /var/log/nginx/access.log vhost;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/letsencrypt/live/mainnet.demo.btcpayserver.org/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/mainnet.demo.btcpayserver.org/privkey.pem;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/mainnet.demo.btcpayserver.org/fullchain.pem;
add_header Strict-Transport-Security "max-age=31536000" always;
#include /etc/nginx/vhost.d/default;
# Here is the main BTCPay Server application
location / {
proxy_pass http://127.0.0.1:23000;
}
# Include the next two stanzas if and only if you want to expose your lightning gRPC & RPC interfaces to the internet
location /lnrpc.Lightning {
grpc_pass grpcs://127.0.0.1:10009;
}
location /lnd-rest/btc/ {
rewrite ^/lnd-rest/btc/(.*) /$1 break;
proxy_pass https://127.0.0.1:8080/;
}
# Include this stanza if you are planning to set up Ride The Lightning (RTL)
location /rtl/ {
proxy_pass http://127.0.0.1:3000/rtl/;
}
}
~$ sudo cp default.conf /etc/nginx/conf.d
~$ sudo systemctl restart nginx

👍 Check

1. Check Let's Encrypt.

It can be a little bit tricky to get everything set up correctly for the Let's Encrypt script to work correctly. Some additional commands are listed below to help with any troubleshooting.

~$ sudo certbot certificates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: mainnet.demo.btcpayserver.org
Domains: mainnet.demo.btcpayserver.org
Expiry Date: 2019-08-10 18:00:31+00:00 (VALID: 79 days)
Certificate Path: /etc/letsencrypt/live/mainnet.demo.btcpayserver.org/fullchain.pem
Private Key Path: /etc/letsencrypt/live/mainnet.demo.btcpayserver.org/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
~$ cat /etc/cron.d/certbot # (check the cron job exists)
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew
~$ sudo tail /var/log/letsencrypt/letsencrypt.log # (check for problems)
2019-05-22 19:36:36,062:DEBUG:certbot.main:certbot version: 0.31.0
~$ sudo certbot renew --dry-run # (test renewal)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates below have not been saved.)
Congratulations, all renewals succeeded. The following certs have been renewed:
/etc/letsencrypt/live/mainnet.demo.btcpayserver.org/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

2. Check NGINX.

~$ sudo nginx -v
nginx version: nginx/1.14.0 (Ubuntu)
~$ sudo sudo netstat -tlnp | grep nginx
nginx version: nginx/1.14.0 (Ubuntu)
~$ sudo journalctl -xe --unit nginx --follow
-- Unit nginx.service has finished starting up.

Bitcoin Daemon

The gateway to the Bitcoin network for BTCPay Server components.

🚚 Install

1. Download the latest binaries from a trusted source such as https://bitcoincore.org/en/download/.

~$ wget https://bitcoincore.org/bin/bitcoin-core-0.18.0/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz
~$ wget https://bitcoincore.org/bin/bitcoin-core-0.18.0/SHA256SUMS.asc

2. Verify the authenticity of the downloads.

The Bitcoin Core code signing key is currently:

"Wladimir J. van der Laan (Bitcoin Core binary release signing key) laanwj@gmail.com") public key: 01EA5486DE18A882D4C2684590C8019E36C2E964

It's advisable to double check the signing key corresponds with other available sources. A good one is https://github.com/bitcoin/bitcoin/tree/master/contrib/verifybinaries.

~$ gpg --receive-key 0x01EA5486DE18A882D4C2684590C8019E36C2E964
~$ gpg --verify SHA256SUMS.asc
gpg: Good signature from "Wladimir J. van der Laan (Bitcoin Core binary release signing key) <laanwj@gmail.com>" [unknown]
~$ sha256sum --ignore-missing -c SHA256SUMS.asc
bitcoin-0.18.0-x86_64-linux-gnu.tar.gz: OK

3. Install the binaries.

~$ tar zxf bitcoin-0.18.0-x86_64-linux-gnu.tar.gz
~$ pushd bitcoin-0.18.0/bin; sudo cp bitcoind bitcoin-cli /usr/bin; popd;
~$ bitcoind --version
Bitcoin Core Daemon version v0.18.0

4. Create the configuration file.

An example configuration file is available on the Bitcoin Core repository at https://github.com/bitcoin/bitcoin/blob/master/share/examples/bitcoin.conf.

Create a bitcoin.conf file to suit your needs. An example file that is suitable for BTCPay Server is shown below. This configuration does not prune blocks which means as of May 2019 you will require 235 GB for the Bitcoin blockchain.

~$ vi bitcoin.conf
mainnet=1
server=1 # need RPC for btcpay.
rpcbind=127.0.0.1 # loopback is default for 0.18.0 but no harm making sure.
whitelist=127.0.0.1 # for nbxplorer.
rpcallowip=127.0.0.1/32 # loopback is default but again no harm.
disablewallet=1 # btcpay does not host a bitcoin wallet.
zmqpubrawblock=tcp://127.0.0.1:28332 # needed for lightning.
zmqpubrawtx=tcp://127.0.0.1:28333 # needed for lightning.

Copy the file to the directory specified in the systemd service file and assign read permissions to all users.

~$ sudo mkdir -p /etc/bitcoin
~$ sudo cp bitcoin.conf /etc/bitcoin
~$ sudo chmod 644 /etc/bitcoin/bitcoin.conf

5. Create a systemd service.

An example systemd service file is available in the Bitcoin Core repository at https://raw.githubusercontent.com/bitcoin/bitcoin/master/contrib/init/bitcoind.service.

Edit the service file depending on your needs.

In the example below the User and Group have been changed and the permissions on the ConfigurationDirectory have been modified to make it usable without needing to explicitly set ownership see this issue.

~$ vi bitcoind.service
[Unit]
Description=Bitcoin daemon
After=network.target
[Service]
ExecStart=/usr/bin/bitcoind -daemon \
-pid=/run/bitcoind/bitcoind.pid \
-conf=/etc/bitcoin/bitcoin.conf \
-datadir=/var/lib/bitcoind
# Process management
####################
Type=forking
PIDFile=/run/bitcoind/bitcoind.pid
Restart=on-failure
# Directory creation and permissions
####################################
User=admin
Group=admin
# /run/bitcoind
RuntimeDirectory=bitcoind
RuntimeDirectoryMode=0710
# /etc/bitcoin
ConfigurationDirectory=bitcoin
ConfigurationDirectoryMode=0755
# /var/lib/bitcoind
StateDirectory=bitcoind
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
# 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
# Deny access to /home.
ProtectHome=true
[Install]
WantedBy=multi-user.target

Once the service file is ready complete the commands below.

~$ sudo cp bitcoind.service /etc/systemd/system
~$ sudo systemctl enable bitcoind
~$ sudo systemctl start bitcoind

6. Create a symbolic link to the bitcoind cookie file.

The bitcoin-cli client needs to authenticate to bitcoind for RPC calls. The easiest way to allow this is to create a symbolic link to the cookie file.

~$ cd ~
~$ ln -s /var/lib/bitcoind/.cookie .bitcoin/.cookie

It's not vital to perform this step but if not done then every bitcoin-cli command needs to specify the path to the cookie file as below.

~$ bitcoin-cli -rpccookiefile=/var/lib/bitcoind/.cookie getblockchaininfo

👍 Check

It will take Bitcoin anywhere from a few hours to a few days to synchronise the blockchain. Use any or all of the commands below to check its status.

~$ sudo systemctl status bitcoind
Active: active (running) since Thu 2019-05-23 18:23:48 UTC; 21min ago
~$ tail /var/lib/bitcoind/debug.log -f
20800000 log2_work=90.667233 tx=416658838 date='2019-05-23T18:46:27Z' progress=1.000000 cache=13.6MiB(103874txo) warning='32 of last 100 blocks have unexpected version'
~$ bitcoin-cli getblockchaininfo
{
"chain": "main",
"blocks": 577444,
"headers": 577444,
...
}

👍 Check Tor + Bitcoin

If Tor was installed prior to the Bitcoin Daemon then it should have automatically registered and begun listening on a torv2 onion address (note support for torv3 onion addresses is in the pipeline).

The easiest way to get your Bitcoin Daemon torv2 address is from the log file:

~$ cat /var/lib/bitcoind/debug.log | grep onion
2019-05-23T18:24:22Z tor: Got service ID 4d4al7v4hj5p7bb6, advertising service 4d4al7v4hj5p7bb6.onion:8333
2019-05-23T18:24:22Z AddLocal(4d4al7v4hj5p7bb6.onion:8333,4)

To change your onion address:

~$ rm /var/lib/bitcoind/onion_private_key
~$ sudo systemctl restart bitcoind
~$ cat /var/lib/bitcoind/debug.log | grep onion
2019-05-23T19:06:30Z tor: Got service ID zrzoqb4e5bengdju, advertising service zrzoqb4e5bengdju.onion:8333
2019-05-23T19:06:30Z AddLocal(zrzoqb4e5bengdju.onion:8333,4)

To check your onion address from a remote host with tor installed:

~$ torsocks --shell
~$ telnet 4d4al7v4hj5p7bb6.onion 8333
Trying 127.42.42.0...
Connected to 127.42.42.0.
Escape character is '^]'.
~$ exit

To connect another bitcoind instance to your new node:

~$ bitcoin-cli addnode "4d4al7v4hj5p7bb6.onion" "add"
~$ bitcoin-cli getaddednodeinfo
{
"addednode": "4d4al7v4hj5p7bb6.onion",
"connected": true,
"addresses": [
{
"address": "4d4al7v4hj5p7bb6.onion:8333",
"connected": "outbound"
}
]
}

NBXplorer

NBXplorer is a dotnet core application that monitors the Bitcoin blockchain for transactions of interest to your BTCPay Server.

🚚 Install

1. Install dotnet core

Check download link for latest version (.Net Core 2.2 at the time of writing)

~$ wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
~$ sudo dpkg -i packages-microsoft-prod.deb
~$ sudo add-apt-repository universe
~$ sudo apt-get install apt-transport-https
~$ sudo apt-get update
~$ sudo apt-get install dotnet-sdk-2.2
~$ dotnet --version
2.2.203

2. Build NBXplorer

~$ cd ~; mkdir -p src; cd src
~/src$ git clone https://github.com/dgarage/NBXplorer
~/src$ cd NBXplorer
~/src/NBXplorer$ ./build.sh

3. Create a systemd service.

An example systemd service file is shown below. Adjust the paths, User and Group accordingly.

~$ vi nbxplorer.service
[Unit]
Description=NBXplorer daemon
Requires=bitcoind.service
After=bitcoind.service
[Service]
WorkingDirectory=/home/admin/src/NBXplorer
ExecStart=/home/admin/src/NBXplorer/run.sh
User=admin
Group=admin
Type=simple
PIDFile=/run/nbxplorer/nbxplorer.pid
Restart=on-failure
[Install]
WantedBy=multi-user.target
~$ sudo cp nbxplorer.service /etc/systemd/system
~$ sudo systemctl enable nbxplorer
~$ sudo systemctl start nbxplorer

👍 Check

~$ sudo journalctl -xe --unit nbxplorer --follow
May 23 19:13:35 btc run.sh[8065]: info: Configuration: Data Directory: /home/admin/.nbxplorer/Main
May 23 19:13:35 btc run.sh[8065]: info: Configuration: Configuration File: /home/admin/.nbxplorer/Main/settings.config
May 23 19:13:35 btc run.sh[8065]: info: Configuration: Network: Mainnet
...
May 23 19:20:04 btc run.sh[8065]: info: Events: BTC: New block 0000000000000000000c405ba5df5f5533359a4393247a0c52d26c458d4dd989 (577449)

If it doesn't start correctly stop the service and run the application directly to get any error messages.

~$ sudo systemctl stop nbxplorer
~$ cd ~; pushd ./src/NBXplorer; ./run.sh; popd

🚨 Update

Updating could break things. Be careful on a live system.

~$ sudo systemctl stop nbxplorer
~$ cd ~; pushd ~/src/NBXplorer; git pull; ./build.sh; popd;
~$ sudo systemctl start nbxplorer

BTCPay Server

Like NBXplorer the BTCPay Server application is also dotnet core. The install steps assume dotnet core was installed in the previous step.

🚚 Install

1. Build BTCPay Server

~$ cd ~; mkdir -p src; cd src
~/src$ git clone https://github.com/btcpayserver/btcpayserver.git
~/src$ cd btcpayserver
~/src/btcpayserver$ ./build.sh

2. Create Postgresql Database.

By default BTCPay Server will store data in a single SQLite file. A more robust option is to use Postgresql which requires the appropriate database and user exist.

~$ sudo -u postgres psql
postgres=# create database btcpay;
postgres=# create user btcpay with encrypted password 'urpassword';
postgres=# grant all privileges on database btcpay to btcpay;
postgres=#\q

3. Create a configuration file.

$ vi btcpay.config
### Database ###
postgres=User ID=btcpay;Password=urpassword;Host=localhost;Port=5432;Database=btcpay;
### Application ###
rootPath="/btcpay" # if you'd like to run BTCPay Server along side other apps
~$ sudo mkdir /etc/btcpay
~$ sudo cp btcpay.config /etc/btcpay
~$ sudo chmod 644 /etc/btcpay/btcpay.config

4. Create a systemd service.

An example systemd service file is shown below. Adjust the paths, User and Group accordingly.

~$ vi btcpay.service
[Unit]
Description=BTCPay Server
Requires=nbxplorer.service
After=nbxplorer.service
[Service]
WorkingDirectory=/home/admin/src/btcpayserver
ExecStart=/home/admin/src/btcpayserver/run.sh --conf=/etc/btcpay/btcpay.config
User=admin
Group=admin
Type=simple
PIDFile=/run/btcpayserver/btcpayserver.pid
Restart=on-failure
[Install]
WantedBy=multi-user.target
~$ sudo cp btcpay.service /etc/systemd/system
~$ sudo systemctl enable btcpay
~$ sudo systemctl start btcpay

👍 Check

~$ sudo journalctl -xe --unit btcpay --follow
-- The start-up result is RESULT.
May 23 20:01:25 btc run.sh[10263]: info: Configuration: Data Directory: /home/admin/.btcpayserver/Main
May 23 20:01:25 btc run.sh[10263]: info: Configuration: Configuration File: /etc/btcpay/btcpay.config
May 23 20:01:25 btc run.sh[10263]: info: Configuration: Network: Mainnet

If it doesn't start correctly stop the service and run the application directly to get any error messages.

~$ sudo systemctl stop btcpay
~$ cd ~; pushd ~/src/btcpayserver --conf=/etc/btcpay/btcpay.config; ./run.sh; popd;

An example of checking information in the database.

~$ sudo -u postgres psql
postgres=# \connect btcpay;
btcpay=# \dt
btcpay=# select * from "Invoices";
btcpay=# \q

🚨 Update

Updating could break things. Be careful on a live system.

~$ sudo systemctl stop btcpay
~$ cd ~; pushd ~/src/btcpayserver; git pull; ./build.sh; popd;
~$ sudo systemctl start btcpay

Lightning Network Daemon (lnd)

🚚 Install

1. Install Go.

~$ sudo apt install make
~$ wget https://dl.google.com/go/go1.12.3.linux-amd64.tar.gz
~$ sha256sum go1.12.3.linux-amd64.tar.gz | awk -F " " '{ print $1 }'
3924819eed16e55114f02d25d03e77c916ec40b7fd15c8acb5838b63135b03df
~$ sudo tar -C /usr/local -xzf go1.12.3.linux-amd64.tar.gz
~$ export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
~$ export GOPATH=~/gocode
~$ go version
go version go1.12.3 linux/amd64

2. Build and install lnd.

~$ go get -d github.com/lightningnetwork/lnd
~$ cd $GOPATH/src/github.com/lightningnetwork/lnd
~$ make
~$ make install # installs to /home/admin/gocode/bin which is $GOPATH/bin
~$ lnd --version
lnd version 0.6.1-beta commit=v0.6.1-beta-12-gf8c824fb1d6c5ef8524148f59ea5650af65af98b
~$ sudo cp $GOPATH/bin/lnd $GOPATH/bin/lncli /usr/bin

3. Create a symbolic link to the Bitcoin configuration file.

lnd looks for bitcoin.conf in a specific location to get necessary RPC and zeromq details.

~$ ln -s /etc/bitcoin/bitcoin.conf ~/.bitcoin/bitcoin.conf

4. Create a configuration file.

~$ vi lnd.conf
[Application Options]
datadir=/var/lib/lnd/data
tlscertpath=/var/lib/lnd/tls.cert
tlskeypath=/var/lib/lnd/tls.key
logdir=/var/lib/lnd/logs
maxlogfiles=3
maxlogfilesize=10
#externalip=1.1.1.1 # change to your public IP address if required.
alias=i_luv_btcpay
listen=0.0.0.0:9375
[Bitcoin]
bitcoin.active=1
bitcoin.node=bitcoind
bitcoin.mainnet=true
[tor]
tor.active=true
tor.v3=true
~$ sudo mkdir -p /etc/lnd
~$ sudo mkdir -p /var/lib/lnd
~$ sudo chown admin:admin -R /var/lib/lnd
~$ sudo cp lnd.conf /etc/lnd
~$ sudo chmod 644 /etc/lnd/lnd.conf

5. Create a systemd service.

An example systemd service file is shown below. Adjust the paths, User and Group accordingly.

~$ vi lnd.service
[Unit]
Description=LND Lightning Network Daemon
Requires=bitcoind.service
After=bitcoind.service
[Service]
ExecStart=/usr/bin/lnd --configfile=/etc/lnd/lnd.conf
ExecStop=/usr/bin/lncli --lnddir /var/lib/lnd stop
PIDFile= /run/lnd/lnd.pid
User=admin
Group=admin
Type=simple
KillMode=process
TimeoutStartSec=60
TimeoutStopSec=60
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
~$ sudo cp lnd.service /etc/systemd/system
~$ sudo systemctl enable lnd
~$ sudo systemctl start lnd

✒️ Configuration

Running a Bitcoin Lightning daemon requires a hot wallet on your BTCPay Server.

Repeating for emphasis.

Running a Bitcoin Lightning daemon requires a hot wallet on your BTCPay Server.

With Bitcoin the protocol has evolved and deterministic key derivation means the keys for your wallet can be kept in a different location to the BTCPay Server. Lightning daemons do not have this facility. Any Bitcoins committed or received in your lightning channels are controlled by private keys that are on your BTCPay Server.

1. Create a symbolic link to the lnd data directory.

The install steps above use /var/lib/lnd as the data directory rather than the default /home/user/.lnd. In order to save typing when using the lncli client it's useful to add a symbolic directory link.

ln -s /var/lib/lnd .lnd

2. Create Lightning wallet.

The first time the lnd is started a new wallet must be created and the backup seed safely recorded (if someone else gets your seed they can steal your funds so keep it safe).

~$ lncli create
Input wallet password:
Confirm wallet password:
---------------BEGIN LND CIPHER SEED---------------
1. above 2. catch 3. start 4. tape
5. sound 6. friend 7. water 8. royal
9. solid 10. poet 11. wisdom 12. match
13. virtual 14. zero 15. slender 16. thrive
17. idle 18. catch 19. robot 20. clay
21. resemble 22. angry 23. work 24. until
---------------END LND CIPHER SEED-----------------

Note that if the symbolic directory link from the previous step was not created the command is:

lncli --lnddir /var/lib/lnd create

3. Unlock the wallet.

Every time lnd is restarted the wallet needs to be unlocked. This is not ideal for a BTCPay Server that can is designed to run unattended but Lighting is still in its infancy.

~$ lncli unlock

👍 Check

~$ lncli getinfo
{
"version": "0.6.1-beta commit=v0.6.1-beta-12-gf8c824fb1d6c5ef8524148f59ea5650af65af98b",
...
}

Check the service:

~$ sudo journalctl -xe --unit lnd --follow
...
May 24 19:21:54 btc lnd[8067]: 2019-05-24 19:21:54.683 [INF] DISC: Broadcasting batch of 27 new announcements
May 24 19:23:24 btc lnd[8067]: 2019-05-24 19:23:24.683 [INF] DISC: Broadcasting batch of 163 new announcements

👍 Check Tor + lnd

As with the Bitcoin daemon if Tor is installed and the configuration file enables it (the one above does) then lnd will automatically register an onion address. In lnd's case torv3 addresses are supported.

The torv3 onion address below is a lot longer than the torv2 one from the Bitcoin daemon section (16 characters compared to 56 characters).

~$ lncli getinfo | grep onion
"029b0e3c05595074afcffdca0fb22fb68a95a9c4698dd20962f647de4891eceabd@liyuvwbbycrvvuzcrsd5rq7svwckabejlsymcxiwzkj3smvlwcsqpjyd.onion:9735"

The Tor address created by lnd can be used to connect to other Lighting peers on the Tor network. The Tor address can work in parallel with an IPv4 or IPv6 address. To register one of those make sure the externalip is set in the lnd configuration file.

🚨 Update

Updating could break things. Be careful on a live system.

~$ sudo systemctl stop lnd
~$ export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
~$ export GOPATH=~/gocode
~$ go get -d github.com/lightningnetwork/lnd
~$ cd $GOPATH/src/github.com/lightningnetwork/lnd
~$ make
~$ make install # installs to /home/admin/gocode/bin which is $GOPATH/bin
~$ lnd --version
lnd version 0.6.1-beta commit=v0.6.1-beta-12-gf8c824fb1d6c5ef8524148f59ea5650af65af98b
~$ sudo cp $GOPATH/bin/lnd $GOPATH/bin/lncli /usr/bin
~$ sudo systemctl start lnd

After the daemon has been restarted the wallet needs to be unlocked:

~$ lncli unlock

If RTL is installed it may have stopped when lnd disappeared so it will also need to be restarted.

~$ sudo systemctl start rtl

Ride The Lightning (RTL)

Ride the Lightning is a Node.js application to manage your Lightning peers, channels, wallet etc.

The advantage of the work that has gone into BTCPay Server is that the RTL web page can be controlled and accessed in the same manner as the BTCPay site.

🚚 Install

1. Install dependencies.

~$ sudo apt install nodejs build-essential npm

2. Build RTL.

~$ cd ~/src
~$ git clone https://github.com/ShahanaFarooqui/RTL.git
~$ cd RTL
~$ npm install

3. Create a configuration file.

A sample RTL.conf configuration file is available here.

~$ vi RTL.conf
[SSO]
rtlSSO=0
rtlCookiePath=/var/lib/rtl
logoutRedirectLink=/login
[Authentication]
macaroonPath=/var/lib/lnd/data/chain/bitcoin/mainnet
lndConfigPath=/etc/lnd/lnd.conf
nodeAuthType=CUSTOM
rtlPass=password
[Settings]
flgSidenavOpened=true
flgSidenavPinned=true
menu=Vertical
menuType=Regular
theme=dark-blue
satsToBTC=false
bitcoindConfigPath=/etc/bitcoin/bitcoin.conf
enableLogging=true
port=3000
lndServerUrl=https://localhost:8080/v1

Note that RTL has different behaviour and requirements compared to the other services documented in theses instructions, specifically: 1. The configuration file needs to exist in RTL's data directory, 2. The RTL process writes to the configuration file. The main change it will do is convert any cleartext password set with rtlPass to a hashed version with rtlPassHashed.

~$ sudo mkdir -p /var/lib/rtl
~$ sudo chown admin:admin -R /var/lib/rtl
~$ sudo cp ~/RTL.conf /var/lib/rtl
~$ sudo chmod 644 /var/lib/rtl/RTL.conf

4. Create a systemd service.

~$ vi rtl.service
[Unit]
Description=Ride The Lightning
Requires=lnd.service
After=lnd.service
[Service]
Environment="RTL_CONFIG_PATH=/var/lib/rtl/RTL.conf"
WorkingDirectory=/var/lib/rtl
ExecStart=/usr/bin/node /home/admin/src/RTL/rtl
User=admin
Group=admin
Type=simple
PIDFile=/run/rtl/rtl.pid
Restart=on-failure
[Install]
WantedBy=multi-user.target
~$ sudo cp rtl.service /etc/systemd/system
~$ sudo systemctl enable rtl
~$ sudo systemctl start rtl

👍 Check

Check the service:

~$ sudo journalctl -xe --unit rtl --follow
...
May 24 19:38:01 btc node[8072]: Console:
May 24 19:38:01 btc node[8072]: Transactions: 10: 1558726681366: INFO: Transaction Received: {}

If it doesn't start correctly stop the service and run the application directly to get any error messages.

~$ sudo systemctl stop rtl
~$ export RTL_CONFIG_PATH=/var/lib/rtl/RTL.conf; pushd ~/src/RTL; node rtl; popd;
Server is up and running, please open the UI at http://localhost:3000

🚨 Update

Updating could break things. Be careful on a live system.

~$ sudo systemctl stop rtl
~$ cd ~; pushd ~/src/RTL; git pull; npm install; popd;
~$ sudo systemctl start rtl

🏁 The End