BTCPay Server is an open-source, self-hosted payment processor for Bitcoin and other cryptocurrencies. It enables merchants and businesses to accept Bitcoin payments directly without relying on third-party payment processors or intermediaries. BTCPay Server offers merchants a secure, privacy-focused, and customizable payment processing solution for accepting Bitcoin and other cryptocurrencies.

In this tutorial, we will show you how to install the BTCPay server on Ubuntu 22.04.

Step 1 – Install Docker CE

Install the packages necessary to add a new repository over HTTPS:

apt install apt-transport-https ca-certificates git

Add Docker’s official repository and GPG key to your system:

echo "deb [signed-by=/etc/apt/keyrings/docker.gpg.key arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
wget --quiet -O - https://download.docker.com/linux/ubuntu/gpg | tee /etc/apt/keyrings/docker.gpg.key

After adding the repository, update the package index:

apt update

Finally, install the latest version of Docker CE:

apt install docker-ce -y

Step 2 – Install BTCPay

Clone the BTCPay Server repository from GitHub to your server machine:

git clone https://github.com/btcpayserver/btcpayserver-docker.git

Change into the directory where you cloned the BTCPay Server repository:

cd ~/btcpayserver-docker/

Export the environment variables that are necessary for BTCPay installation.

export BTCPAY_HOST="btc.linuxbuz.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

Finally, install the BTCPay server using the following script.

. ./btcpay-setup.sh -i

Output:

[+] Running 8/0
 ✔ Container tor                          Running                                                                                                                  0.0s 
 ✔ Container btcpayserver_bitcoind        Running                                                                                                                  0.0s 
 ✔ Container btcpayserver_lnd_bitcoin     Running                                                                                                                  0.0s 
 ✔ Container generated_lnd_bitcoin_rtl_1  Running                                                                                                                  0.0s 
 ✔ Container generated_postgres_1         Running                                                                                                                  0.0s 
 ✔ Container generated_nbxplorer_1        Running                                                                                                                  0.0s 
 ✔ Container tor-gen                      Running                                                                                                                  0.0s 
 ✔ Container generated_btcpayserver_1     Running                                                                                                                  0.0s 
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

To check the BTCPay server status, run the following command:

systemctl status btcpayserver.service

Output:

● btcpayserver.service - BTCPayServer service
     Loaded: loaded (/etc/systemd/system/btcpayserver.service; enabled; vendor preset: enabled)
     Active: active (exited) since Sat 2024-04-06 03:57:39 UTC; 3min 2s ago
    Process: 33105 ExecStart=/bin/bash -c . "/etc/profile.d/btcpay-env.sh" && cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" && . helpers.sh && btcpay_up (code=exited>
   Main PID: 33105 (code=exited, status=0/SUCCESS)
        CPU: 206ms

You can also verify all running containers using the following command:

docker ps

Output:

CONTAINER ID   IMAGE                              COMMAND                  CREATED         STATUS         PORTS                                                                                    NAMES
aac50ed3aa24   shahanafarooqui/rtl:0.14.1         "/sbin/tini -g -- no…"   4 minutes ago   Up 4 minutes   3000/tcp                                                                                 generated_lnd_bitcoin_rtl_1
0576ec248536   btcpayserver/btcpayserver:1.13.0   "/app/docker-entrypo…"   4 minutes ago   Up 4 minutes   49392/tcp                                                                                generated_btcpayserver_1
cfa1ce79b857   btcpayserver/lnd:v0.17.4-beta      "/sbin/tini -g -- /d…"   4 minutes ago   Up 4 minutes   8080-8081/tcp, 0.0.0.0:9735->9735/tcp, :::9735->9735/tcp                                 btcpayserver_lnd_bitcoin
60ea110f3f31   btcpayserver/docker-gen:0.10.7     "/usr/local/bin/dock…"   4 minutes ago   Up 4 minutes                                                                                            tor-gen
b830c0ae554d   nicolasdorier/nbxplorer:2.5.2      "dotnet NBXplorer.dll"   4 minutes ago   Up 4 minutes   32838/tcp                                                                                generated_nbxplorer_1
1dcf56ea4abd   btcpayserver/bitcoin:26.0          "/entrypoint.sh bitc…"   4 minutes ago   Up 4 minutes   8332-8333/tcp, 18332-18333/tcp, 18443-18444/tcp, 28332-28334/tcp, 39388/tcp, 43782/tcp   btcpayserver_bitcoind
bb7f0cd045f0   btcpayserver/tor:0.4.8.10          "./entrypoint.sh tor"    4 minutes ago   Up 4 minutes   9050-9051/tcp                                                                            tor
27182eb40921   btcpayserver/postgres:13.13        "/migrate-docker-ent…"   4 minutes ago   Up 4 minutes   5432/tcp                                                                                 generated_postgres_1

Step 3 – Configure the BTCPay Server

Next, you will need to expose port 49392 for the BTCPay server. To do so, edit the BTCPay server configuration file.

nano ~/btcpayserver-docker/Generated/docker-compose.generated.yml

Add the following lines in the btcpayserver section.

    ports:
    - "49392:49392"

Save and close the file, then restart the BTCPay service to apply the changes.

systemctl restart btcpayserver

Step 4 – Configure Nginx for BTCPay

To configure Nginx as a reverse proxy for the BTCPay Server, you’ll need to create an Nginx server block (also known as a virtual host) to handle incoming requests and forward them to the BTCPay Server instance running on Docker.

If Nginx is not already installed on your system, you can install it using the following command:

apt install -y nginx

Create a new Nginx configuration file for BTCPay Server:

nano /etc/nginx/conf.d/btcpay-server.conf

Add the following configuration.

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;
}
# 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 btc.linuxbuz.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 edit the Nginx main configuration file.

nano /etc/nginx/nginx.conf

Add the following line after the line http{:

server_names_hash_bucket_size 64;

Save the file, then reload the Nginx service to apply the changes.

systemctl reload nginx

Step 5 – Enable SSL for the BTCPay Server

To enable SSL for BTCPay Server using Let’s Encrypt, you can use Certbot, a tool provided by Let’s Encrypt, to obtain and install SSL certificates for your domain.

apt install certbot python3-certbot-nginx

Run Certbot to obtain an SSL certificate for your domain.

certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email [email protected] -d btc.linuxbuz.com

Output:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for btc.linuxbuz.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/btc.linuxbuz.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/btc.linuxbuz.com/privkey.pem
This certificate expires on 2024-07-05.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for btc.linuxbuz.com to /etc/nginx/conf.d/btcpay-server.conf
Congratulations! You have successfully enabled HTTPS on https://btc.linuxbuz.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Step 6 – Access the BTCPay Server

Now, open your web browser and access the BTCPay web interface using the URL https://btc.linuxbuz.com. You will see the BTCPay account creation page.

Define your email and password and click on the Create account. You will see the store creation page.

Define your store name, default currency, and price source, then click on Create Store. On the following page, you will see the BTCPay dashboard.

Conclusion

You can now set up your own self-hosted BTCPay Server instance, empowering you to take full control of your payment processing infrastructure. With BTCPay Server, you can leverage the security and transparency of Bitcoin while enjoying the flexibility and customization options provided by a self-hosted solution. By hosting your own BTCPay Server, you can eliminate reliance on third-party payment processors, protect the privacy of your customers’ transactions, and maintain full control over your financial transactions. You can now host your BTCPay server on dedicated hosting from Atlantic.Net!