btpay

Production Deployment

This guide covers deploying BTPay on a Linux server with Gunicorn, Nginx, and systemd.

Prerequisites

Installation

# Create system user
sudo useradd -r -s /bin/false -d /opt/btpay btpay

# Clone and set up
sudo mkdir -p /opt/btpay
sudo chown btpay:btpay /opt/btpay
cd /opt/btpay

sudo -u btpay git clone https://github.com/user/btpay.git .
sudo -u btpay python3 -m venv .venv
sudo -u btpay .venv/bin/pip install --require-hashes -r requirements.lock
sudo -u btpay .venv/bin/pip install -e . --no-deps

Configuration

Create a production config file:

sudo -u btpay cat > /opt/btpay/config.py << 'EOF'
# Generate secrets with: python3 -c "import secrets; print(secrets.token_hex(32))"
SECRET_KEY = 'your-64-char-hex-string-here'
DEV_MODE = False

# Reference number encryption keys
# Generate with: python3 -c "import secrets; print(secrets.token_hex(16))"
REFNUM_AES_KEY = 'your-32-char-hex-string'
REFNUM_HMAC_KEY = 'your-32-char-hex-string'

# JWT secrets (one per purpose)
JWT_SECRETS = {
    'admin': 'your-random-secret-1',
    'login': 'your-random-secret-2',
    'api':   'your-random-secret-3',
    'invite': 'your-random-secret-4',
}

# Optional: SMTP for email notifications
SMTP_CONFIG = {
    'host': 'smtp.example.com',
    'port': 587,
    'username': 'your-smtp-user',
    'password': 'your-smtp-password',
    'from_email': 'payments@yourdomain.com',
    'from_name': 'Your Business',
}

# Optional: Tor privacy
# SOCKS5_PROXY = 'socks5h://127.0.0.1:9050'
EOF

chmod 600 /opt/btpay/config.py

Generate Secrets

# Generate all required secrets at once
python3 -c "
import secrets
print(f'SECRET_KEY = \"{secrets.token_hex(32)}\"')
print(f'REFNUM_AES_KEY = \"{secrets.token_hex(16)}\"')
print(f'REFNUM_HMAC_KEY = \"{secrets.token_hex(16)}\"')
for purpose in ['admin', 'login', 'api', 'invite']:
    print(f'  \"{purpose}\": \"{secrets.token_hex(24)}\",')
"

Create Admin User

cd /opt/btpay
sudo -u btpay .venv/bin/flask --app app user-create \
  --email admin@yourdomain.com \
  --first-name Admin \
  --last-name User

You’ll be prompted for a password.

Gunicorn

The included config at deploy/gunicorn.conf.py is production-ready:

# Test it
sudo -u btpay .venv/bin/gunicorn -c deploy/gunicorn.conf.py wsgi:app

Key settings:

Override via environment:

Env Var Default Description
BTPAY_BIND 127.0.0.1:5000 Bind address
BTPAY_THREADS 4 Worker threads
BTPAY_LOG_LEVEL info Log level

systemd

Install the service:

sudo cp /opt/btpay/deploy/btpay.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable btpay
sudo systemctl start btpay

Check status:

sudo systemctl status btpay
sudo journalctl -u btpay -f

The service includes security hardening:

Nginx

Edit deploy/nginx.conf and replace:

Install:

sudo cp /opt/btpay/deploy/nginx.conf /etc/nginx/sites-available/btpay
sudo ln -s /etc/nginx/sites-available/btpay /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Let’s Encrypt

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d btpay.yourdomain.com

Tor (Optional)

For maximum privacy, route all external connections through Tor:

  1. Install Tor:
    sudo apt install tor
    sudo systemctl enable tor
    
  2. Add to config.py:
    SOCKS5_PROXY = 'socks5h://127.0.0.1:9050'
    
  3. Optionally expose as a Tor hidden service by adding to /etc/tor/torrc:
    HiddenServiceDir /var/lib/tor/btpay/
    HiddenServicePort 80 127.0.0.1:5000
    
  4. Get your .onion address:
    sudo cat /var/lib/tor/btpay/hostname
    

libsecp256k1 (Optional)

For faster BIP32 key derivation, build the C library:

cd /tmp
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
./autogen.sh
./configure --enable-module-recovery
make
sudo make install
sudo ldconfig

BTPay automatically detects and uses it if available. Without it, a pure Python fallback is used.

Backups

Automatic Backups

BTPay auto-saves data every 60 seconds and keeps the last 5 backups. Data is stored in data/.

Manual Backup

sudo -u btpay .venv/bin/flask --app app db-backup

External Backup

Back up the entire data/ directory:

# Simple rsync backup
rsync -av /opt/btpay/data/ /backup/btpay/

# Or with a cron job
echo "0 */6 * * * btpay cd /opt/btpay && .venv/bin/flask --app app db-backup" | sudo tee /etc/cron.d/btpay-backup

Restore

sudo systemctl stop btpay
sudo -u btpay cp /backup/btpay/*.json /opt/btpay/data/
sudo systemctl start btpay

Monitoring

Health Check

curl http://localhost:5000/health

Returns {"status": "ok"} when the server is running.

Logs

# Follow live logs
sudo journalctl -u btpay -f

# Recent errors only
sudo journalctl -u btpay --since "1 hour ago" -p err

In production, logs are JSON-formatted for easy parsing by log aggregators.

Data Stats

sudo -u btpay .venv/bin/flask --app app db-stats

Updating

cd /opt/btpay
sudo -u btpay git pull
sudo -u btpay .venv/bin/pip install --require-hashes -r requirements.lock
sudo -u btpay .venv/bin/pip install -e . --no-deps
sudo systemctl restart btpay

FreeBSD

BTPay works on FreeBSD. Key differences:

Troubleshooting

Server won’t start:

Data lost after restart:

Rate limited:

Exchange rates not updating: