Install a BTCPay server

De Organic Design
BitPay is a cool service that makes it very easy for client to purchase items on your site with Bitcoin and other Altcoins, and the seller gets full invoicing capabilities. Unfortunately BitPay is a pay service and is closed-source and centralised, they have forced choices onto their merchants against their best interests a number of times as discussed here. Fortunately Nicolas Dorier has put in the hard yards to create a open source free version called BTCPay. It's written in dotNet which sucks a little, but it can be fully deployed very easily with his Docker image so that there's no Microsoft messing up your server :-) This page is my procedure for setting up the Docker image and is based on his excellent tutorial here.

Preparing the server

It's best to run this on a VPS that has at least 2GB of RAM, 80GB of disk space and a kernel version of at least 3.1 (the more recent the better). I prefer Debian, but any distro capable of running Docker should be fine.

Before starting the installation of BTCPay it's best if you have your server already located at it's final domain and have the hostname of the server set to that name as well. Set it with hostname -b YOURDOMAIN and also in /etc/hostname and add it as a localhost alias in /etc/hosts.

Nicolas' installation method expects to be able to SSH in as root (using an RSA key) so don't disable root logins like you probably normally would. But you can, and should, disable password logins and add your RSA public key to /root/.ssh/authorized_keys.

It's best to install Docker first since it may not be available in your distro's package repo by default, for Debian, follow the official installation guide here.

You'll also need to install git and then you're ready to run through the BTCpay installation steps.


Now we can get on with the actual BTCPay installation, first clone the repo:

git clone
cd btcpayserver-docker

Set up all the environment variables (see the tutorial for a better explanation of these).

export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_CRYPTO2="ltc"
export BTCPAYGEN_CRYPTO3="dash"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-s"

Note1: BTCPAYGEN_ADDITIONAL_FRAGMENTS uses about 50GB for the blockchain when set to opt-save-storage-s, but it can also be set to opt-save-storage-xs as well which uses about 25GB and opt-save-storage-xxs which uses about 5GB, but note that lightning requires a minimum of opt-save-storage-xs.

Note2: You include other supported altcoins by putting them in successive BTCPAYGEN_CRYPTO2,3,4 etc, here we're including Bitcoin, Litecoin and Dash.

Set up LetsEncrypt to generate an SSL certificate for you BTCPay site:

export ACME_CA_URI=""
ssh-keygen -t rsa -f /root/.ssh/id_rsa_btcpay -q -P ""
cat /root/.ssh/ >> /root/.ssh/authorized_keys
export BTCPAY_HOST_SSHKEYFILE=/root/.ssh/id_rsa_btcpay

Now you can run the installation script (note the leading dot):

. ./ -i

Note: You can make changes to the environment variables and re-run the installation at any time without affecting your existing data.

If there are no errors you now have a running BTCpay server! You'll probably need to wait for 15min or so for the LetsEncrypt cert to activate, then go to your server at the domain you specified and register yourself. The first registered account is automatically the administrator.

If the HTTPS is still not functioning after half an hour, try restarting the associated Docker container:

docker restart letsencrypt-nginx-proxy-companion

And if you need to restart the entire BTCpay server, you can do so without rebooting like this:

systemctl restart btcpayserver

Note that you'll need to wait a couple of days for the nodes to sync! You can see the status at the bottom right of your server's webpage.

You have a BTCPay server! But now what?

Coke machine using BTCpay server
First you need to create a new store, and a new POS app connected to the store. This is all quite self-explanatory, but setting up a wallet so that the POS app has a payment method is not so straight forward. Using it with a NanoS hardware wallet is easiest, but otherwise, like me, you can use Electrum desktop wallet.

To do this, go to you store settings, and click "modify" on BTC in the "derivation schemes" section. Then sign in to your wallet in Electrum and open the "Information" window in the "Wallet" menu. In there you'll see a master public key and a script type. Copy the master public key and paste it into the "DerivationScheme" box in BTCPay, then check which address type matches in the list at the bottom of the BTCPay screen, and append the dash and square bracketed bit to your derivation scheme, for example -[legacy] or -[p2sh]. Then click "continue" and check that the list of addresses matches the address shown in the "addresses" tab of Electrum. See this video for more clarification.

Electrum is a very straight forward wallet to use for BTCpay, but you can actually use Exodus too. You can get your xpub key from the developer menu under "Assets" and then use it with -[legacy] appended in BTCpay. This works fine for Bitcoin, but for other assets you'll need to refresh the chain (click the asset logo at the top) before the payment will show up because it's sent to a change address rather than the primary address. It's ok for Bitcoin since multiple payment addresses are allowed.

Once you have a store, a POS app and a wallet, you can paste a payment form into your site based on the HTML below or on the examples shown in the POS app's settings, or in the stores settings under "Pay Button". Once a payment form is submitted a new entry can be seen in the BTCpay "invoices" screen.

<form method="POST" action="">
  <input type="hidden" name="amount" value="1" />
  <input type="hidden" name="email" value="" />
  <input type="hidden" name="orderId" value="CustomOrderId" />
  <input type="hidden" name="redirectUrl" value="" />
  <button type="submit">Pay!</button>


Upgrading leaves unused older images, so you need to regularly delete those, and also you may need to docker volume prune out any old unused volumes for example if you removed support for a coin.

See also