How to Set Up BTCPay Server on Ubuntu 22.04/20.04 with Docker
BTCPay server is an open-source, self-hosted cryptocurrency payment processor. With BTCPay Server, you don’t need to pay fees to a third-party payment processor, and since it’s peer-to-peer payment, it’s resistant to censorship. This tutorial will be showing you how to set up BTCPay server on Ubuntu.
BTCPay Server Features
- Your own Bitcoin payment processor.
- No need to worry about account closure by a third party like Paypal.
- Get rid of unreasonable fees set by third-party payment processors.
- Integration with Common eCommerce platforms like Magento, Shopify, WooCommerce, Joomla Virtuemart, Prestashop and Shopware.
- You can add an unlimited amount of users and stores.
- Supports the Bitcoin Lightning Network
- Accepts altcoins.
- Integration with Quickbooks Online Accounting.
- Plugins
- Powerful APIs
Note: With BTCPay Server, you don’t need to pay fees to third-party payment processors (like BitPay) anymore, but there are still Bitcoin transaction fees, which can be reduced by using a Lightning node and another tool called payout processor in BTCPay Server.
Server Requirement
- At least 2 CPU cores and 4GB RAM
- 600 GB disk for data storage
We will be using the BTCPay Docker, which simplifies the setup process. It’s not recommended to set up BTCPay manually in a production environment.
Step 1: Install Docker on Ubuntu 22.04 Server
Docker is included in the Ubuntu software repository. However, to ensure that we have the latest version, we will have to install it from Docker’s APT repository. Log into your server via SSH, then run the following command to add the Docker repository to your Ubuntu server.
echo "deb [signed-by=/etc/apt/keyrings/docker.gpg.key arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
Next, run the following command to import the Docker GPG key to Ubuntu system so that APT can verify package integrity during installation.
wget --quiet -O - https://download.docker.com/linux/ubuntu/gpg | sudo tee /etc/apt/keyrings/docker.gpg.key
And because this repository uses HTTPS connection, which I recommend all software repositories should be using, we also need to install apt-transport-https
and ca-certificates
package.
sudo apt install apt-transport-https ca-certificates
Finally, update the package index on your Ubuntu system and install docker-ce
(Docker Community Edition).
sudo apt update sudo apt install docker-ce
Once Docker is installed, the Docker daemon should be automatically started. You can check its status with:
systemctl status docker
If it’s not running, then start the daemon with the following two commands:
sudo systemctl restart docker.socket sudo systemctl restart docker.service
And enable autostart at boot time:
sudo systemctl enable docker
Check Docker version.
docker -v
Sample output:
Docker version 20.10.18, build 370c289
Step 2: Install and Start the BTCPay Docker Container
This step must be executed as the root user, so switch to root.
sudo su -
Clone the BTCPay Server Github repository.
sudo apt install git cd ~ git clone https://github.com/btcpayserver/btcpayserver-docker.git
It will be saved under the ~/btcpayserver-docker/
directory. Change to this directory.
cd ~/btcpayserver-docker/
Before starting the BTCPay Docker container, we need to set several environment variables by running the following commands one by one.
export BTCPAY_HOST="btcpay.example.com"
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_REVERSEPROXY="empty"
export BTCPAYGEN_EXCLUDE_FRAGMENTS="$BTCPAYGEN_EXCLUDE_FRAGMENTS;nginx-https"
export BTCPAYGEN_LIGHTNING="lnd"
export BTCPAY_ENABLE_SSH=true
export
is a Linux shell command that set environment variables.
Where
- BTCPAY_HOST: You need to replace
btcpay.example.com
with your preferred hostname for your BTCPay instance. For example, I usebtcpay.linuxbabe.com
. - NBTICOIN_NETWORK: choose to run on
mainnet
,testnet
orregnet
. You need to run on mainnet in production environment. - BTCPAYGEN_CRYPTO01: Choose the crypto coin your BTCPAY instance will support. For now, you can choose BTC. Altcoins can be added later.
- BTCPAYGEN_REVERSEPROXY: You can choose among
nginx
,traefix
andemtpy
: We don’t want the Docker container to act as reverse proxy. We can use existing Nginx web server as reverse proxy. - BTCPAYGEN_EXECLUDE_FRAMENTS: We don’t want the Docker container to generate TLS certificates. We will obtain and install a free Let’s Encrypt TLS certificate later.
- BTCPAYGEN_LIGHTING: You can use
lnd
orclightning
for lightning networking support - BTCPAY_ENABlE_SSH: Allow BTCPAY to manage SSH authorized keys.
To check the value of an environment variable, you can use the echo command. For example.
echo $BTCPAY_HOST
Next, run the following command to install and start the BTCPay Docker container.
. ./btcpay-setup.sh -i
Sample output:
Installed bitcoin-cli.sh to /usr/local/bin: Command line for your Bitcoin instance Installed bitcoin-lncli.sh to /usr/local/bin: Command line for your Bitcoin LND instance Installed btcpay-clean.sh to /usr/local/bin: Command line for deleting old unused docker images Installed btcpay-down.sh to /usr/local/bin: Command line for stopping all services related to BTCPay Server Installed btcpay-restart.sh to /usr/local/bin: Command line for restarting all services related to BTCPay Server Installed btcpay-setup.sh to /usr/local/bin: Command line for restarting all services related to BTCPay Server Installed btcpay-up.sh to /usr/local/bin: Command line for starting all services related to BTCPay Server Installed btcpay-admin.sh to /usr/local/bin: Command line for some administrative operation in BTCPay Server Installed btcpay-update.sh to /usr/local/bin: Command line for updating your BTCPay Server to the latest commit of this repository Installed changedomain.sh to /usr/local/bin: Command line for changing the external domain of your BTCPay Server
Check systemd service status:
sudo systemctl status btcpayserver.service
Output:
Check Docker containers:
sudo docker ps
Output:
As you can see, the btcpayserver/btcpayserver
Docker container doesn’t expose the port to the host OS. Edit the Docker Compose file.
nano ~/btcpayserver-docker/Generated/docker-compose.generated.yml
Add the following lines in the btcpayserver
section.
ports: - "49392:49392"
Like this:
Save and close the file. Then restart btcpayserver.service.
sudo systemctl restart btcpayserver
Now check the Docker container status again.
sudo docker ps
You will see that the host OS port 49392 is mapped to the Docker port 49392.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS cf182b7d5e6f btcpayserver/btcpayserver:1.6.11 "/app/docker-entrypo…" 14 minutes ago Up 14 minutes 0.0.0.0:49392->49392/tcp
If made an error in the environment variables, you can change them, then run the setup script again and restart btcpayserver.service
.
Step 3: Configure Nginx Reverse Proxy
Install Nginx web server from the default Ubuntu software repository.
sudo apt install -y nginx
Create an Nginx virtual host file for BTCPay Server.
sudo nano /etc/nginx/conf.d/btcpay-server.conf
Add the following lines in this file.
# 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 btcpay.linuxbabe.com;
listen 80;
access_log /var/log/nginx/btcpay.access;
error_log /var/log/nginx/btcpay.error;
client_max_body_size 100M;
# Here is the main BTCPay Server application
location / {
proxy_pass http://127.0.0.1:49392;
}
# 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/;
}
}
Save and close the file. Then test Nginx configurations.
sudo nginx -t
If the test is successful, reload Nginx.
sudo systemctl reload nginx
Step 4: Enable HTTPS
To encrypt HTTP traffic, we can enable HTTPS by installing a free TLS certificate issued from Let’s Encrypt. Run the following command to install Let’s Encrypt client (certbot) on Ubuntu server.
sudo apt install certbot python3-certbot-nginx
Next, run the following command to obtain and install TLS certificate.
sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email [email protected] -d btcpay.example.com
Where
--nginx
: Use the nginx plugin.--agree-tos
: Agree to terms of service.--redirect
: Force HTTPS by 301 redirect.--hsts
: Add the Strict-Transport-Security header to every HTTP response. Forcing browser to always use TLS for the domain. Defends against SSL/TLS Stripping.--staple-ocsp
: Enables OCSP Stapling. A valid OCSP response is stapled to the certificate that the server offers during TLS.
The certificate should now be obtained and automatically installed.
Step 5: Using the BTCPay Server Web Interface
Now you can go to https://btcpay.example.com
to register an admin account.
Once the admin account is created, BTCPay Server automatically disables new user registration. You can re-enable it if you want to.
On the bottom-right corner, you can check the Bitcoin node syncing status.
It’s recommended to wait for this process to finish before doing anything else in the BTCPay server dashboard.
Step 6:
Now you need to
- create a store
- create a wallet
- set up lighting node
Click the Create Store button to get started. If you don’t own an e-commerce store, you can still create a store on BTCPAY server. A store is an entity that will recieve payment from others.
Next, click the Set up a wallet button.
You can import your existing wallet or create a new wallet. Even though I have an existing Bitcoin, I still prefer to create a new wallet on BTCPAY Server.
There are two types of wallets you can create:
- Hot wallet
- Watch-only wallet
I choose to create a watch-only wallet as it’s more secure.
There are 4 address types:
- Segwit
- Segwit Wrapped
- Legacy
- Taproot
I choose the recommended Segwit address type. You can also set a passphrase for your wallet to make it more secure.
Then BTCPAY will display the recover phrase for your wallet. You need to write it down on paper and store it safely. Click the Done button and the wallet is created.
Next, click the set up a lighting node button. You can choose to use the BTCPAY internal lightning node or use a custom lightning node. I choose the easy route: Use internal node. Click the Save button.
In the BTC Lightning Settings page, you can enable Lightning URL (LNURL) for invoices.
How to Upgrade BTCPAY Server
When a new version of BTCPay Server is released, run the following command as root to update it.
btcpay-update.sh
Then edit the Docker Compose file.
sudo nano /root/btcpayserver-docker/Generated/docker-compose.generated.yml
Add the following lines in the btcpayserver
section.
ports: - "49392:49392"
Like this:
Save and close the file. Then restart btcpayserver.service.
sudo systemctl restart btcpayserver
Wrapping Up
I hope this tutorial helped you set up BTCPAY on Ubuntu. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂
Hello,
How do we accept other crypto like USDT Tron| USDT ERC20,, how do we accept ETH for example? is there a way to do it ?
Sorry, I just noticed that it’s CRYPTO and not CRYPT0(zero)… 🙂
Hi, im using ubuntu server 22.04 and got an error:
BTCPAYGEN_CRYPT01 should not be empty
But when I do:
echo $BTCPAYGEN_CRYPT01
I got:
btc
Any advice?
You don’t have to edit /root/btcpayserver-docker/Generated/docker-compose.generated.yml after each update. It’s possible to create a custom fragment which will keep ports exposed after updates. To do so you should create a fragment inside /root/btcpayserver-docker/docker-compose-generator/docker-fragments. For example, create fragment named opt-expose-btcpayserver.custom.yml(it’s important that fragment ends with .custom.yml). Inside fragment add:
services:
btcpayserver:
ports:
– “49392:49392″
Save file and then do following:
export BTCPAYGEN_ADDITIONAL_FRAGMENTS=”$BTCPAYGEN_ADDITIONAL_FRAGMENTS;opt-expose-btcpayserver.custom”
. ./btcpay-setup.sh -i
hello,
whe i try to execute sudo certbot –nginx –agree-tos –redirect –hsts –staple-ocsp –email [email protected] -d btcpay.againsturb.com
(I have replaced my email in my code)
I get
nginx restart failed:
nginx: [emerg] “server_names_hash_bucket_size” directive is duplicate in /etc/nginx/conf.d/btcpay.againsturb.domain
how can i fix this?