BTCPay Server Privacy Setup Guide

Complete Technical Documentation for Self-Hosted Bitcoin Payment Processing

🛡️ Why This Matters

Until recently, a parent would return home with an actual pay packet containing cash. Financial privacy didn't need protection because it existed naturally in the system.

Today, every financial transaction is monitored, conversations are scanned, and virtual profiles are built for marketing and political manipulation. This comprehensive technical guide helps you reclaim your privacy and accept Bitcoin payments securely using your own infrastructure.

Remember: Every journey begins with a single step. Don't let perfect be the enemy of good. Technology is a tool for freedom, not oppression.

Want to understand the deeper "why" behind Bitcoin before diving into the technical setup? 📚 Complete book: Bitcoin Through New Eyes - Organized journey from scientific metaphors to practical understanding 📧 Academic frameworks: Freeonlineuser's Substack - 15+ posts exploring Bitcoin through scientific lenses (biology, physics, economics, philosophy) 🧠 Raw intellectual evolution: Bitcoin Understanding - A Journey Through Time - The personal thought process behind the academic work (2017-2024) From cosmic Dyson spheres to cellular mitochondria - see Bitcoin through multiple scientific paradigms, then build your own sovereign infrastructure.

🏗️ Architecture Decision: Choose Your Approach

📋 Two Setup Options Available:

Option A: Direct Home Server (Simpler)

Option B: VPS Proxy + Home Server (Recommended for Privacy)

Choose ONE approach and follow only those instructions. Mixing both approaches will create configuration conflicts.

🔒 Phase 1: Privacy Foundation

1Secure Mobile Device

Purchase a Google Pixel phone (6 Pro or newer) that supports GrapheneOS. Check compatibility at https://grapheneos.org/faq#supported-devices

NEVER buy GrapheneOS pre-installed. Always install it yourself from the official website to ensure security. Pre-installed devices could be compromised.

Install GrapheneOS following the official guide at https://grapheneos.org

2Anonymous Communication

Purchase an eSIM with phone number using non-KYC Bitcoin via Silent Link. This provides SMS verification for services without revealing your identity.

Note that X(Twitter) and Telegram don't accept these non-KYC numbers for verification. Ask yourself: why do they need to know where you live?

3VPN Service

Subscribe to Mullvad VPN using Bitcoin. Mullvad is excellent for privacy with no logging policy.

Alternative: PIA (Private Internet Access) is decent for easy installation across multiple devices if you prefer convenience over maximum privacy.

4Email Privacy

Create a new email with proton.me. Verify your account with SMS to your new eSIM number. Use this email exclusively for your website setup initially, then expand to daily use once your domain is configured.

✅ Privacy-Focused Tools to Use:

❌ Avoid These Surveillance Tools:

🌐 Phase 2: Domain & Hosting Infrastructure

5Domain Registration

Purchase a domain from Orange Website. They accept Bitcoin Lightning payments and provide excellent service. Get RapidSSL Standard for the green certificate lock.

# Total cost approximately $40/year # Payment flow: Pay via BitPay → Electrum → Bitcoin Lightning Domain registration: ~$12-15/year RapidSSL Standard: ~$25/year Total: ~$40/year for professional setup

6VPS Setup (Option B Only)

Skip this step if using Option A (Direct Home Server)

For privacy protection, use a VPS to hide your home IP. After testing multiple providers, 1984.hosting is excellent at $6/month with Bitcoin payments.

Browse more Bitcoin VPS options at bitcoin-vps.com. Many providers now accept Bitcoin payments.

6aVPS Firewall Configuration

Critical for Option B: Unlike home servers protected by router NAT, your VPS is directly exposed to the internet and needs firewall protection.

# Configure VPS firewall (UFW) for security sudo ufw default deny incoming sudo ufw default allow outgoing # Allow essential services sudo ufw allow ssh # SSH management access sudo ufw allow 80/tcp # HTTP (Let's Encrypt + redirects) sudo ufw allow 443/tcp # HTTPS (BTCPay traffic) # Enable firewall sudo ufw enable # Verify configuration sudo ufw status
Test SSH connection immediately after enabling the firewall. If you lose access, most VPS providers offer console access through their web panel to fix firewall rules.

7DNS Configuration

Option A - Direct Home Server DNS:

# Point your subdomain directly to your home IP Name: btcpay.yourdomain.com Type: A Value: YOUR_HOME_STATIC_IP # Your home IP will be visible in DNS lookups

Option B - VPS Proxy DNS:

# Point your subdomain to VPS IP (hides home IP) Name: btcpay.yourdomain.com Type: A Value: YOUR_VPS_IP # Home IP remains hidden

Set up your daily email address using your new domain. Configure Thunderbird for email on both phone and PC with SSL encryption enabled in SMTP settings.

🔌 Phase 3: Network Configuration

8Static IP & Port Forwarding

Option A - Direct Home Server:

Contact your ISP for a static IP, then configure router port forwarding:

Router Port Forwarding (Option A): Service Name External Port Protocol Internal Port Server IP BTCPay HTTP 80 TCP 80 192.168.1.100 BTCPay HTTPS 443 TCP 443 192.168.1.100 # Standard web ports - simple configuration

Option B - VPS Proxy:

Configure router to forward custom port to avoid ISP blocking:

Router Port Forwarding (Option B): Service Name External Port Protocol Internal Port Server IP BTCPay VPS Proxy 15080 TCP 80 192.168.1.100 # VPS connects to your home on port 15080 # No port 443 needed - VPS handles SSL
Give your BTCPay server a static local IP via DHCP reservation to ensure the IP doesn't change.

₿ Phase 4: BTCPay Server Installation

9Server Preparation

Use a dedicated always-on computer running Linux. Ubuntu Server LTS, Linux Mint LTS, or Debian are recommended. The server must remain powered on 24/7 to process payments.

Alternative: Install Oracle VirtualBox and spin up a Linux VM if you don't have dedicated hardware. Ensure the VM starts automatically with your host system.

10Parmanode Installation

Visit https://parmanode.com/install to learn about the installation process. Parmanode is the easiest way to get a complete Bitcoin stack:

curl https://parmanode.com/install.sh | sh

From the Parmanode menu, install in this order:

  1. Bitcoin Core (full node)
  2. Electrum Server
  3. Lightning Network implementation
  4. BTCPay Server

11System Updates & Dependencies

sudo apt update && sudo apt upgrade -y sudo apt-get install nginx certbot python3-certbot-nginx -y # Secure: Only allow specific commands without password (for automation) sudo visudo # Add this line with your username for targeted permissions: yourusername ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx, /usr/bin/systemctl restart btcpayserver, /usr/sbin/nginx

🔧 Phase 5: Nginx Configuration

12Option A: Direct Home Server Nginx

Use this configuration if you chose Option A (Direct Home Server)

sudo nano /etc/nginx/sites-available/btcpay
# Option A: Direct home server configuration
# Protocol and WebSocket mapping
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# HTTP to HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name btcpay.yourdomain.com;

    # ACME challenge for SSL certificates
    location ~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/html;
        try_files $uri =444;
    }

    # Redirect all other traffic to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS Server
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name btcpay.yourdomain.com;

    # SSL certificates (will be added by certbot)
    ssl_certificate /etc/letsencrypt/live/btcpay.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/btcpay.yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Security headers for protection against common attacks
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    location / {
        proxy_pass http://127.0.0.1:23001;  # BTCPay Server (3003 on Umbrel)
        proxy_set_header Host $http_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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

# Default server block
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 444;
}

13Option B: Home Server Nginx (VPS Proxy)

Use this configuration if you chose Option B (VPS Proxy)

sudo nano /etc/nginx/sites-available/btcpay
# Option B: Home server behind VPS proxy
# Protocol and WebSocket mapping
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# Primary server - accepts traffic from VPS only
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name btcpay.yourdomain.com;

    # Security: Only allow connections from your VPS
    allow YOUR_VPS_IP;
    deny all;

    location / {
        proxy_pass http://127.0.0.1:23001;  # BTCPay Server (3003 on Umbrel)
        proxy_set_header Host $http_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 $proxy_x_forwarded_proto;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

# Default catch-all
server {
    listen 80;
    listen [::]:80;
    server_name _;
    return 444;
}

14Option B: VPS Nginx Configuration

Configure this on your VPS if you chose Option B

# On your VPS, install nginx and configure: sudo apt update && sudo apt install nginx certbot python3-certbot-nginx -y sudo nano /etc/nginx/sites-available/btcpay
# VPS nginx configuration
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# HTTPS Server - SSL termination happens here
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name btcpay.yourdomain.com;

    # SSL certificates (will be added by certbot)
    ssl_certificate /etc/letsencrypt/live/btcpay.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/btcpay.yourdomain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Security headers for protection against common attacks
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    location / {
        proxy_pass http://YOUR_HOME_IP:15080;  # Your home server
        proxy_set_header Host $http_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 $proxy_x_forwarded_proto;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

# HTTP redirect
server {
    listen 80;
    listen [::]:80;
    server_name btcpay.yourdomain.com;

    location ~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/html;
        try_files $uri =444;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# Default block
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 444;
}

15Enable Nginx Configuration

# Enable the site (both Option A and B) sudo ln -sf /etc/nginx/sites-available/btcpay /etc/nginx/sites-enabled/ # Remove default site sudo rm -f /etc/nginx/sites-enabled/default # Test configuration sudo nginx -t # If test passes, reload nginx sudo systemctl reload nginx

🔐 Phase 6: SSL Certificate Setup

16SSL Certificate Generation

Option A - Direct Home Server:

Generate SSL certificates on your home server:

# Test certificate generation first sudo certbot certonly --webroot -w /var/www/html \ -d btcpay.yourdomain.com \ -m webmaster@yourdomain.com \ --agree-tos --dry-run # If dry run succeeds, generate live certificate sudo certbot certonly --webroot -w /var/www/html \ -d btcpay.yourdomain.com \ -m webmaster@yourdomain.com \ --agree-tos

Option B - VPS Proxy:

Generate SSL certificates on your VPS only:

# Run this on your VPS, not home server sudo certbot certonly --webroot -w /var/www/html \ -d btcpay.yourdomain.com \ -m webmaster@yourdomain.com \ --agree-tos

17Certificate Auto-Renewal

# Test certificate renewal sudo certbot renew --dry-run # Check automatic renewal (should be configured automatically) sudo crontab -l

⚙️ Phase 7: BTCPay Server Configuration

18BTCPay Reverse Proxy Settings

cd /opt/parmanode/btcpayserver/ # or your BTCPay data directory nano .env # Add these lines for reverse proxy support: BTCPAY_ROOTPATH=/ BTCPAY_HOST=btcpay.yourdomain.com BTCPAY_EXTERNALURL=https://btcpay.yourdomain.com # For Option B (VPS proxy), also add: FORWARDED_PROTO_HEADER_NAME=X-Forwarded-Proto

Save with Ctrl+X, then Y, then Enter. Restart BTCPay Server:

sudo systemctl restart btcpayserver # or reboot system if unsure how to restart BTCPay

⚡ Phase 8: Lightning Network Configuration

19Understanding Inbound Liquidity

To receive Lightning payments, you need inbound liquidity. This is the amount of Bitcoin that can be sent TO your node through Lightning channels.

Methods to Obtain Inbound Liquidity:

1. Exchange Method (Tested):

2. Lightning Service Providers (LSPs):

3. Direct Channel Opening:

🧪 Phase 9: Testing & Verification

20System Verification

# Test SSL certificate and connectivity curl -I https://btcpay.yourdomain.com # Should return: HTTP/1.1 302 Found (redirect to login) sudo nginx -t sudo systemctl status nginx

21Create Test Invoice

  1. Browse to https://btcpay.yourdomain.com
  2. Complete BTCPay Server initial setup
  3. Create a test store
  4. Generate a test Bitcoin invoice
  5. Verify Lightning and on-chain payment options appear
  6. Test a small payment to confirm everything works

🔄 Phase 10: Dynamic IP Management (Option B Only)

Skip this section if using Option A (Direct Home Server)

22SSH Key Setup

Create SSH keys for automated VPS access from your home server:

# On your home server, generate SSH key pair ssh-keygen -t rsa -b 4096 -f ~/.ssh/vps_key # Copy public key to your VPS ssh-copy-id -i ~/.ssh/vps_key.pub user@YOUR_VPS_IP # Test the connection ssh -i ~/.ssh/vps_key user@YOUR_VPS_IP "echo 'SSH works'"

23Privacy-Enhanced IP Monitor Script

Create this script on your home server. Unlike traditional scripts that update constantly, this only connects to your VPS when your IP actually changes - providing massive privacy improvement:

nano /usr/local/bin/ip-monitor.sh
#!/bin/bash
# Privacy-enhanced IP monitoring script
# Only updates VPS when IP actually changes (99.99% exposure reduction)

LOG_FILE="/var/log/ip-update.log"
VPS_USER="your_vps_username"
VPS_HOST="YOUR_VPS_IP"
VPS_PORT="22"  # Use custom port if configured
SSH_KEY="/home/yourusername/.ssh/vps_key"
LOCK_FILE="/tmp/ip-monitor.lock"

# Function to log with timestamp
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
}

# Prevent multiple simultaneous runs
if [ -f "$LOCK_FILE" ]; then
    exit 0
fi
touch "$LOCK_FILE"

# Cleanup on exit
trap 'rm -f "$LOCK_FILE"' EXIT

# Get current public IP
NEW_IP=$(curl -s --max-time 10 ifconfig.me)

if [ -z "$NEW_IP" ]; then
    log "ERROR: Failed to get public IP"
    exit 1
fi

# Get current IP from VPS nginx config
OLD_IP=$(ssh -i $SSH_KEY -p $VPS_PORT -o StrictHostKeyChecking=no $VPS_USER@$VPS_HOST "grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:15080' /etc/nginx/sites-available/btcpay | head -1 | cut -d: -f1" 2>/dev/null)

if [ -z "$OLD_IP" ]; then
    log "ERROR: Failed to get current IP from VPS"
    exit 1
fi

# Check if IP changed - ONLY UPDATE IF DIFFERENT
if [ "$NEW_IP" != "$OLD_IP" ]; then
    log "IP changed from $OLD_IP to $NEW_IP - updating VPS"
    
    # Update VPS nginx config with backup/rollback protection
    UPDATE_RESULT=$(ssh -i $SSH_KEY -p $VPS_PORT -o StrictHostKeyChecking=no $VPS_USER@$VPS_HOST "
        # Backup original config
        sudo cp /etc/nginx/sites-available/btcpay /etc/nginx/sites-available/btcpay.backup &&
        # Replace IP in config
        sudo sed -i 's/proxy_pass http:\/\/.*:15080/proxy_pass http:\/\/$NEW_IP:15080/g' /etc/nginx/sites-available/btcpay &&
        # Test nginx config and reload, or rollback on failure
        if sudo nginx -t; then
            sudo systemctl reload nginx && echo 'SUCCESS'
        else
            echo 'NGINX_TEST_FAILED - Rolling back'
            sudo cp /etc/nginx/sites-available/btcpay.backup /etc/nginx/sites-available/btcpay &&
            sudo nginx -t && sudo systemctl reload nginx
            echo 'ROLLBACK_COMPLETED'
        fi
    " 2>&1)
    
    if [[ $UPDATE_RESULT == *"SUCCESS"* ]]; then
        log "VPS updated successfully to $NEW_IP"
        # Test if the new IP is reachable
        if timeout 10 curl -s http://$NEW_IP:15080 > /dev/null; then
            log "New IP $NEW_IP is reachable"
        else
            log "WARNING: New IP $NEW_IP may not be reachable"
        fi
    elif [[ $UPDATE_RESULT == *"ROLLBACK_COMPLETED"* ]]; then
        log "ERROR: Nginx test failed, rolled back to $OLD_IP"
    else
        log "ERROR: Failed to update VPS - $UPDATE_RESULT"
    fi
else
    # IP unchanged - exit silently (no log spam)
    exit 0
fi

24Automate with Cron (Privacy-Enhanced)

# Make script executable chmod +x /usr/local/bin/ip-monitor.sh # Setup cron job to run every 5 minutes (checks more frequently but only updates when needed) crontab -e # Add this line: */5 * * * * /usr/local/bin/ip-monitor.sh
Privacy Improvement: This script runs every 5 minutes but only creates VPS connections when your IP actually changes. Typical home IPs change 4-6 times per year, reducing exposure from 52,560 connections/year to ~6 connections/year - a 99.99% privacy improvement!

📚 Additional Resources & Acknowledgments

🙏 This Guide Built Upon Excellent Work By:

📖 Further Reading:

🔧 Common Issues & Solutions

Issue: "502 Bad Gateway" error

Issue: SSL certificate not working

Issue: Can't access BTCPay externally

Issue: VPS can't connect to home server (Option B)

Issue: IP monitor script not updating

✅ Success!

If you've followed this guide completely, you now have:

Remember: Technology is a tool for freedom, not oppression. You've taken a significant step toward financial privacy and independence.

Financial Privacy is a Human Right.