One of the largest Bitcoin payment providers BitPay has been under the fire from Bitcoiners for quite a while.

The community called for a boycott which was smartly used by a developer Nicolas Dorier to his advantage.

Nicolas has created an open-source and self-hosted BitPay-compatible payment gateway called BTCPayServer which has been well received by the community.

While there are many guides on how to set it up using Docker and other methods, I like to have control over what I install on my server while also learning how it works.

If you for whatever reason prefer a manual installation of BTCPayServer, I wrote a step-by-step guide on how to do that.

This tutorial is written for Ubuntu 18.04 but should work on older versions and other Debian-based distributions too.

Before you start, make sure you have Bitcoin Core and Lightning Network node running.

#1 Install Dependencies

To run the BTCPayServer you will need to install .NET Core SDK, NBXplorer and PostgreSQL.

Install .NET Core SDK

Go to your Downloads folder or any other folder that you use to store temporary files:

cd ~/Downloads

and download Microsoft Packages necessary for the .NET Core SDK:

wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -sr)/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list

Update the package cache and install the .NET Core:

sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install dotnet-sdk-3.1

#2 Install NBXplorer

We'll need to install NBXplorer In order to track incoming on-chain transactions.

Create the source folder if you haven't already and open it:

mkdir ~/source
cd ~/source

Clone the repository and build the code:

git clone https://github.com/dgarage/NBXplorer
cd NBXplorer
./build.sh

Create the data folder:

mkdir -p ~/.nbxplorer/Main
cd ~/.nbxplorer/Main

and a new config file:

touch settings.config

Open the file with the editor of your choice and add the following lines:

btc.rpc.auth=<bitcoind rpc user>:<bitcoind rpc password>
port=24445
mainnet=1

Make sure to use your bitcoind's rpc login credentials. You can find them with the command:

cat ~/.bitcoin/bitcoin.conf | grep rpc

Test if everything is set up correctly:

/usr/bin/dotnet ~/source/NBXplorer/NBXplorer/bin/Release/netcoreapp2.1/NBXplorer.dll -c ~/.nbxplorer/Main/settings.config

If so, hit the ctrl+c to kill the process and download the Systemd service:

cd /usr/lib/systemd/system
sudo wget https://gist.githubusercontent.com/mariodian/de873b969e70eca4d0a7673efd697d0a/raw/acfc70c5694cd53d8a3df7ff54a35ff2caba7532/nbxplorer.service

Edit the file according to your environment.

Enable the service, start it and check the status:

sudo systemctl enable nbxplorer.service
sudo service nbxplorer start
sudo service nbxplorer status

If you see no errors go to the next step.

#3 Install PostgreSQL

I wasn't able to set up BTCPayServer with MySQL/MariaDB so I was forced to use PostgreSQL.

Install it first and open a shell prompt as a newly created system user:

sudo apt install postgresql postgresql-contrib
sudo -i -u postgres

Create a new database user:

createuser --pwprompt --interactive

Type in the following (you can change satoshi, to any username you like):

Create a new database user and set roles

Create a new database:

createdb -O satoshi btcpayserver

If you see no errors exit the shell:

exit

#4 Install BTCPayServer

Clone the repository and build the code:

cd ~/source
git clone https://github.com/btcpayserver/btcpayserver.git
cd btcpayserver
./build.sh

Create the data folder:

mkdir -p ~/.btcpayserver/Main
cd ~/.btcpayserver/Main

and a new config file:

touch settings.config

Get the LND's certificate fingerprint and paste it into the below config file.

openssl x509 -noout -fingerprint -sha256 -inform pem -in ~/.lnd/tls.cert

Open settings.config and add the following lines:

network=mainnet
port=23001
bind=0.0.0.0
chains=btc
BTC.explorer.url=http://127.0.0.1:24445
BTC.lightning=type=lnd-rest;server=https://127.0.0.1:8080/;macaroonfilepath=~/.lnd/data/chain/bitcoin/mainnet/admin.macaroon;certthumbprint=<finger print>
postgres=User ID=<your db user>;Password=<your db password>;Host=localhost;Port=5432;Database=btcpayserver;

Change the highlighted "variables" according to your settings.

Check if everything is working correctly.

/usr/bin/dotnet run -p ~i/source/btcpayserver/BTCPayServer/BTCPayServer.csproj -c ~/.btcpayserver/Main/settings.config --network=mainnet

If so, hit ctrl+c to kill the process and download the Systemd service:

cd /usr/lib/systemd/system
sudo wget https://gist.githubusercontent.com/mariodian/07bb13da314e2a321784b380f543651a/raw/6cef554d9e8311e683a017d5e63a07822dee7642/btcpayserver.service

Edit the file based on your environment.

Enable the service, start it and check whether it's running correctly:

sudo systemctl enable btcpayserver.service
sudo service btcpayserver start
sudo service btcpayserver status

Congrats, you just got past the hardest part!

#5 Allow incoming connections (optional)

If you want to run your server remotely, you will have to open a port 23001.

First, go to your router settings and find a section along the lines of "Virtual Server" or "Port Forwarding" and set up a port forwarding on the above-mentioned port.

Then go back to your linux machine and open the port with iptables:

sudo iptables -A INPUT -p tcp --dport 23001 -j ACCEPT

If you use iptables-save run the following too:

sudo iptables-save > /etc/iptables/rules.v4

You should be now able to connect to your server from a different machine.

#6 Setup BTCPayServer

Go to your BTCPayServer administration, Register a new admin account and login.

Now, go to Stores and click Create a new store. When done go to the store settings and scroll down to Derivation Scheme.

Set up your on-chain wallet

Under the "BTC" click Modify and on your computer/phone open a wallet that supports BIP32.

For the purpose of the tutorial, I will use Electrum.

It's recommended to create a fresh wallet instead of using an old one so you don't have to bother rescanning balances on your addresses.

When finished, click Wallet -> Information, copy the Master Public Key, paste it back to BTCPayServer administration, check Enabled, and save it.

Add a master public key of your BIP32-compatible wallet

Next, scroll down to Lightning nodes (Experimental) and click Modify.

Set up your Lightning Network node

Your Connection string should be set up but if not, paste in the following:

type=lnd-rest;server=https://127.0.0.1:8080/;macaroonfilepath=/home/satoshi/.lnd/data/chain/bitcoin/mainnet/admin.macaroon;certthumbprint=<your cert fingerprint>

Remember to add your LND's certificate fingerprint that you've got earlier and change the home directory to your own one.

Your Lightning Network node configuration

Click Test connection and if everything's ok check Enabled and click Submit.

In the case, the server runs on a separate machine that you want to access via a domain name, go to Server Settings -> Maintenance, and in the section Change domain name add your name (you will, of course, have to buy it first).

Add your own domain name

You will also have to add a CNAME or A DNS record with your domain name provider depending on your setup. Sorry, I can't help you on that one, there are too many providers.

Now you should be able to access your BTCPayServer administration with the new domain name like so: http://domain.ltd:23001.

To create a POS terminal, go to Apps -> Create a new app and fill out the short form. You will then be taken to the app settings where you can change the list of items via a template.

An example Point-of-sale tea store

You can also add a simple Pay button to your website that you can configure in Stores -> Settings -> Pay Button as well as create an invoice manually in Stores -> Invoices -> Create a new invoice. that you can then send to a customer.

BTCPay's payment gateway supporting BTC both on-chain and via Lightning Network

Of course, the front-end design of the payment gate is fully customizable so you can set your own logo and colors.

#7 Setup SSL certificate and reverse proxy (Optional)

You need to set up a reverse proxy first. It will map the local BTCPay port to 80 and 443 so that it can be accessible from http(s)://your.server.com.

Choose one of the options below.

But before you start, don't forget to open ports 80 and 443 (please refer to the step 5) on your firewall.

NGINX (option 1)

First, lets install NGINX that will be used as a reversed proxy if you haven't done so already.

sudo apt-get install nginx

Create virtual host:

sudo touch /etc/nginx/sites-available/btcpay

And add the following content:

server {
  listen 80;
  server_name btcpay.freedomnode.com;
  return 301  https://$host$request_uri;
}

server {
  listen 443 sll;
  server_name btcpay.freedomnode.com;

  include                /etc/letsencrypt/options-ssl-nginx.conf;

  access_log    /var/log/nginx/btcpayserver.access.log;

  location / {
    proxy_set_header    Host $host;
    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 $scheme;

    # Fix the “It appears that your reverse proxy set up is broken" error.
    proxy_pass          http://localhost:23001;
    proxy_redirect      http://localhost:23001 https://btcpay.freedomnode.com;
    proxy_read_timeout  90;
  }
}

Make sure to edit the content to match your hostname.

Enable the host:

sudo ln -s /etc/nginx/sites-available/btcpay /etc/nginx/sites-enabled/

and restart the server:

sudo systemctl restart nginx

Now, Install Let's Encrypt certificate and follow the on-screen instructions:

sudo letsencrypt certonly --nginx -d btcpay.freedomnode.com

Make sure to change your hostname in the command above.

Restart the web server again:

sudo systemctl restart nginx

Apache 2 (option 2)

Lets install Apache that will be used as a reversed proxy if you haven't done so already.

sudo apt-get install apache2

Enable required modules:

sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_ajp
sudo a2enmod deflate
sudo a2enmod headers
sudo a2enmod proxy_balancer
sudo a2enmod proxy_connect
sudo a2enmod proxy_html

Create virtual host:

sudo touch /etc/apache2/sites-available/btcpay.conf

and add the following content:

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName btcpay.freedomnode.com
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =btcpay.freedomnode.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Change ServerName based on your needs and enable the host:

sudo a2ensite btcpay.conf

Create a virtual host that will be accessed over SSL:

sudo touch /etc/apache2/sites-available/btcpay-le-ssl.conf

and add the following content:

<IfModule mod_ssl.c>
  <VirtualHost *:443>
    ServerAdmin [email protected]
    ServerName btcpay.freedomnode.com
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    ProxyPass "/" "http://127.0.0.1:23001/"
    ProxyPassReverse / "http://127.0.0.1:23001/"
    ProxyPreserveHost On

    Include /etc/letsencrypt/options-ssl-apache.conf
  </VirtualHost>
</IfModule>

Again, edit ServerName to match your hostname.

Enable the virtual host:

sudo a2ensite btcpay-le-ssl.conf

and restart the server:

sudo systemctl restart apache2

Create the certificate (don't forget to edit the hostname):

sudo letsencrypt certonly --apache -d btcpay.freedomnode.com

and restart the server again:

sudo systemctl restart apache2

Set up an external URL

After the certificate and reverse proxy are set up, go back to ~/.btcpayserver/Main/settings.config and add:

externalurl=https://btcpay.freedomnode.com

Once again, change the server name to your own one.

Remove bind=0.0.0.0 from the configuration because the remote connection will be redirected through the proxy from now.

Also, don't forget to open ports 80 and 443 (please refer to the step 5) on your firewall.

Restart BTCPayServer:

sudo service btcpayserver restart

Open your browser and check if your newly installed SSL certificate works correctly.

*****

I hope you find this tutorial helpful. If you run into any issues let me know in the comments section below.

Feel free to share your online stores running BTCPayServer in the comments too.

P.S. If you appreciate Nicolas' work please support him on his Donation page.

Please let us know what you think in the comments section below.