Launch pricing: every plan costs 30% less than the cheapest offshore competitor we track. See the benchmarkEvery plan 30% under the cheapest offshore host

Knowledge base · VPS

How to self-host BTCPay Server on a VPS

Self-host BTCPay Server on a VPS: what a pruned node needs, which plan fits, the official Docker install on Ubuntu 24.04, Lightning, backups and security.

Updated 10 min read

In this guide

  • BTCPay's starting point for a pruned, Bitcoin-only server is 2 vCPUs, 4 GB of RAM and 50 GB of SSD, which our Cutter plan covers.
  • Point a domain at the server, open ports 80 and 443, then source the official btcpay-setup.sh script.
  • Register as soon as the site loads: the first account becomes the server administrator.
  • Connect a hardware wallet or an xpub, so the server never holds your seed.
  • Run btcpay-backup.sh, copy the archive off the server, and back up Lightning channels separately.
VPS8 sections
All guides
On this page
  1. BTCPay Server requirements and the right plan
  2. Why self-host BTCPay Server on a VPS
  3. What an offshore, no-KYC host changes, and what it does not
  4. How to self-host BTCPay Server, step by step
  5. Keep it running: updates, backups and disk space
  6. Secure BTCPay Server and your wallet
  7. Email notifications and port 25
  8. Frequently asked questions

To self-host BTCPay Server, you need a Linux VPS sized for a pruned Bitcoin node (BTCPay's starting point: 2 vCPUs, 4 GB of RAM and 50 GB of SSD), a domain pointing to it and ports 80 and 443 open. Install it with the official btcpayserver-docker script; BTCPay's documentation puts the first sync at one to five days.

These steps use an Offshore VPS with Ubuntu 24.04 LTS or Debian 12 and root access, as in getting started. Replace btcpay.example.com with your hostname and SERVER_IP with your server's IPv4 address.

BTCPay Server requirements and the right plan

The official Docker deployment runs BTCPay Server, PostgreSQL, NBXplorer, Bitcoin Core, Nginx with automatic HTTPS and Tor on one machine. A BTCPay Server pruned node downloads and checks every block but keeps only recent ones, up to its profile's target. BTCPay's server specifications size the disk as 10 GB for the host, 15 GB for Bitcoin's chainstate, plus that target:

SetupPruning profile (blocks kept)Disk by BTCPay's formulaPlan that fitsPrice a month
Test, Bitcoin onlyopt-save-storage-xxs (5 GB)30 GBSloop: 1 vCPU, 2 GB RAM, 40 GB NVMe$3.49
Shop, Bitcoin only (BTCPay's starting point)opt-save-storage-xs (25 GB)50 GBCutter: 2 vCPUs, 4 GB, 70 GB$5.49
Bitcoin and Lightningopt-save-storage-s (50 GB)75 GBSchooner: 4 vCPUs, 8 GB, 160 GB$12.49
Lightning, busier storesopt-save-storage (100 GB)125 GBBrigantine: 6 vCPUs, 16 GB, 240 GB$19.99
Bitcoin and MoneroBitcoin as above; Monero pruned by default250 GB or moreFrigate: 12 vCPUs, 32 GB, 500 GB$47.99
Unpruned nodeNoneAbout 771 GB of blocks, growingDedicated server, 2 × 1 TB NVMe or moreFrom $97.49

These are bare figures: BTCPay says to add headroom, and each plan here has at least 10 GB to spare. The Sloop is below the 4 GB, 2-core starting point, though BTCPay's deployment FAQ still names 2 GB as the minimum; the Dinghy (1 GB, 25 GB) is below every documented minimum. Traffic is unmetered under fair use, which covers the first download of the whole chain.

When you need an unpruned node

Transaction indexing (opt-txindex), ElectrumX and the bundled Mempool explorer need the whole chain: about 771 GB of blocks on 25 September 2026, per blockchain.com's chart, before undo files and indexes (Bitcoin Core's download page still says about 600 GB, plus 5 to 10 GB a month). No VPS plan holds that, not even the Flagship's 640 GB. On a dedicated server with 2 × 1 TB NVMe, such as the Ryzen 7 7700 ($97.49), RAID 1 leaves 1 TB with little room to grow and RAID 0 gives 2 TB without redundancy; the Ryzen 9 7950X ($175.99) and EPYC 7402P ($211.99) have 2 × 1.92 TB, enough for RAID 1.

BTCPay Lightning: Core Lightning, LND or Phoenixd

Lightning is optional: BTCPAYGEN_LIGHTNING selects clightning (Core Lightning), lnd or phoenixd. Core Lightning and LND publish TCP port 9735 for peers; Phoenixd opens none. BTCPay gives no memory figure for each, but Lightning adds an always-on service, liquidity management and stricter backups. Avoid the 5 GB profile with it; BTCPay's FAQ asks for 80 GB of storage. Apps such as ThunderHub require LND. To add it later, export the variable and source the setup again, as in step 3. Receiving also needs inbound liquidity: channels that others, or a paid provider, open toward your node.

Why self-host BTCPay Server on a VPS

BTCPay Server hosting takes three forms: a third-party host serving many merchants from one instance, a machine at home, or your own server. BTCPay's third-party hosting page explains the risks of the first: the host's node can listen to your transactions, a malicious host could run a modified BTCPay that swaps your xpub for its own, and you should assume it may know everything about your usage. A home server exposes your home IP address. A BTCPay Server VPS avoids both: you pick the version, hold the database with your invoices, and payments go straight to your wallet.

What an offshore, no-KYC host changes, and what it does not

What changes: our account is an email address and a password, nothing else, and you pay from your own wallet in Bitcoin, Ethereum, Monero, Tether (USDT) or Solana, with no card or ID. A no-KYC VPS leaves no identity document behind your payment server: pay in BTC, as for a Bitcoin VPS, or privately in XMR with a Monero VPS. You also pick which of seven countries' law applies. What does not change:

  • Your IP address and hostname are public: every customer who opens an invoice connects to them.
  • Bitcoin is public: each invoice gets a new address, but amounts and timing stay on the blockchain.
  • Buyer details your checkout collects sit in your database, under the privacy law that applies to your business.
  • The law still applies: taxes, consumer and payment rules where you trade, and the server country's law, including the Digital Services Act in our EU locations.
  • Our acceptable use policy applies: fraud against real people, such as fake shops and carding, is zero-tolerance.
  • Tor is not anonymity: the deployment adds an onion address, which BTCPay's FAQ says "doesn't make you anonymous at all".

How to self-host BTCPay Server, step by step

1. Point a domain at the server

At your DNS provider, create an A record for a hostname such as btcpay.example.com with your server's IPv4 address. The bundled Nginx gets a Let's Encrypt certificate for it, and port 80 must be reachable for the challenge. Check that the name returns SERVER_IP:

getent ahostsv4 btcpay.example.com

2. Open the firewall

Allow SSH first (your own port if you changed it), then HTTP, HTTPS and, for Core Lightning or LND, 9735:

apt update
apt install -y ufw git
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 9735/tcp
ufw enable

Docker's published ports bypass UFW through Docker's own NAT rules, so UFW cannot hide BTCPay, but it protects everything else. Do not use an nftables file with flush ruleset instead: as our hardening guide warns, it deletes Docker's rules.

3. Clone the repository and set the variables

Work in a root login shell, as the README does: log in as root, or run sudo su - from your sudo user. Then run its commands with your hostname:

mkdir BTCPayServer
cd BTCPayServer
git clone https://github.com/btcpayserver/btcpayserver-docker
cd btcpayserver-docker
export BTCPAY_HOST="btcpay.example.com"
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_LIGHTNING="none"
export BTCPAYGEN_REVERSEPROXY="nginx"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-xs"
. ./btcpay-setup.sh -i
BTCPAY_HOST
Your hostname; setup rejects anything that is not a valid domain name.
NBITCOIN_NETWORK
mainnet, or testnet to experiment.
BTCPAYGEN_CRYPTO1
btc; BTCPAYGEN_CRYPTO2="xmr" adds Monero.
BTCPAYGEN_LIGHTNING
none, clightning, lnd or phoenixd.
BTCPAYGEN_REVERSEPROXY
nginx, which obtains and renews the HTTPS certificate.
BTCPAYGEN_ADDITIONAL_FRAGMENTS
Separated by semicolons, with one pruning profile; setup refuses opt-txindex next to one. When you change the list later, include the profile again, or pruning turns off and the node stops with "Block files have previously been pruned".
BTCPAY_ENABLE_SSH
Found in older guides; the current script ignores it.

4. Run the setup script

Keep the leading dot: the script must be sourced, and without -i it only prints its options. With -i, it installs Docker and a pinned Docker Compose when missing, generates the stack, saves your settings in /etc/profile.d/btcpay-env.sh, adds a btcpayserver systemd service for boot and starts it, which it says can take 5 to 10 minutes.

5. Register the admin account at once

Open https://btcpay.example.com and register right away: the first account becomes the server administrator, and Let's Encrypt logs every certificate publicly, so your hostname is no secret. BTCPay then turns public registration off by default: check that Enable public user registration is off under Server Settings > Policies. If you see only Login and never registered, someone else did, and BTCPay's FAQ says to redeploy. Without SMTP there is no email password reset, so keep the password in a password manager.

6. Let the node sync

The site opens before the first sync ends, which BTCPay's synchronization FAQ puts at one to five days. Check progress with:

bitcoin-cli.sh getblockchaininfo

The node is synced when blocks equals headers and initialblockdownload is false. BTCPay cannot reliably detect payments before then, so accept none.

7. Create a store and connect a wallet

Registration leads to store creation: a name, a default currency and a rate provider. Then connect the store's wallet, in the order of BTCPay's wallet guide:

  • A hardware wallet through the BTCPay Server Vault app, or a wallet file from Electrum or Wasabi.
  • An xpub, typed in or scanned as a QR code.
  • Never the seed: "you should never type wallet seed words on any internet connected device."

BTCPay uses a new address for every invoice, while most wallets watch only about 20 unused addresses, the gap limit: after a run of unpaid invoices, raise it (Electrum, Sparrow and Bitcoin Core allow this), or payments seem to go missing.

Keep it running: updates, backups and disk space

Updates

Update in a root login shell, or with Update under Server Settings > Maintenance:

btcpay-update.sh

The update pulls the repository, regenerates the stack, recreates the containers, then deletes every unused Docker image on the host, BTCPay's or not, unless BTCPAY_UPDATE_CLEAN is false. Back up and read the release notes before significant upgrades.

Backups

cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
./btcpay-backup.sh

The backup script dumps the databases, stops the stack, archives the Docker volumes, secrets and dumps, then restarts. It skips blockchain data, caches, logs and LND's channel database, and keeps LND's wallet and channel.backup. The archive, /var/lib/docker/volumes/backup_datadir/_data/backup.tar.gz, is overwritten at each run and stays on the server: set BTCPAY_BACKUP_PASSPHRASE to encrypt it, and copy it off with restic or Borg, as in our snapshots and backups guide. The stack is down meanwhile, so pick a quiet hour, as in BTCPay's crontab example:

SHELL=/bin/bash
PATH=/bin:/usr/sbin:/usr/bin:/usr/local/bin
15 4 * * * /root/BTCPayServer/btcpayserver-docker/btcpay-backup.sh

Restore with ./btcpay-restore.sh on a server set up the same way, and test that once.

Lightning needs more: BTCPay warns that "broadcasting a revoked state can cause you to lose all funds in that channel." With LND, keep the seed from Server Settings > Services > LND Seed Backup and an off-site copy of channel.backup, refreshed whenever a channel opens or closes; with Core Lightning, follow its own guidance. Never restore a VPS snapshot of a Lightning node taken before its latest payments. Without Lightning, a snapshot is a quick undo: run btcpay-down.sh, request the snapshot, and run btcpay-up.sh once it shows as done.

Disk space and sync status

A full disk stops Bitcoin Core, and BTCPay then shows the node as always starting. Check with:

df -h /var/lib/docker
docker system df
bitcoin-cli.sh getblockchaininfo

With pruning, size_on_disk stays near the profile's target while the database and images grow. Keep BTCPay running at all times so the node stays in sync, and add these checks to your own monitoring: we never email you.

Secure BTCPay Server and your wallet

  • Registration stays off; invite other users from Server Settings.
  • Two-factor authentication: turn it on in your account settings (authenticator app or U2F key). If you lose the device, root can remove it with ./btcpay-admin.sh disable-multifactor YOUR_ACCOUNT_EMAIL in the repository folder, per the server settings FAQ.
  • SSH: log in with keys, as in the hardening guide. Setup adds a restricted root key for the Maintenance actions and may change PermitRootLogin no to prohibit-password in /etc/ssh/sshd_config. In our test, the hardening guide's file, read first, kept root refused, so BTCPay hides those actions. Update from the shell, or set PermitRootLogin forced-commands-only in that file, which admits root only with a forced command, and add root to AllowUsers.
  • No seed on the server. On a KVM host, the provider can technically read a VPS's disk and memory. With a hardware wallet or an xpub, an intruder or the host could watch your payments but not spend them. A BTCPay hot wallet and an internal Lightning node hold private keys: keep only working balances there.

Email notifications and port 25

BTCPay can email password resets, invitations and store events such as a settled invoice, over SMTP set under Server Settings > Email server or in a store's settings. Without SMTP, its notifications guide says, there is "no easy way" to reset a password. Our network closes outbound port 25 by default. That blocks direct delivery to other mail servers, not authenticated submission to a relay: enter your mail provider's SMTP host, port 587 and login, then send the test email. The provider sees what you send, so skip SMTP if that matters.

Frequently asked questions

How much does it cost to self-host BTCPay Server?

The software is free, with no subscriptions or transaction fees; you pay for the server and a domain. BTCPay's starting point (2 vCPUs, 4 GB of RAM, 50 GB of SSD) is our Cutter at $5.49 a month; with Lightning, a Schooner at $12.49. A $100 top-up, the minimum, earns a 10% bonus: about 20 months of a Cutter.

Can I run BTCPay Server on a 2 GB VPS?

Only as a test. BTCPay's deployment FAQ lists 2 GB of RAM as the minimum, but its newer sizing guide starts at 4 GB and 2 cores. Our 2 GB Sloop (1 vCPU, 40 GB NVMe) fits Bitcoin without Lightning on the opt-save-storage-xxs profile, with a slow first sync. For a live shop, use a Cutter.

Do I need a full Bitcoin node for BTCPay Server?

You need a validating node, not the whole chain on disk. The deployment's Bitcoin Core checks every block, and a pruning profile keeps 5 to 100 GB of recent ones. Only transaction indexing, ElectrumX and the bundled Mempool explorer need an unpruned node, today a dedicated server. For a node without BTCPay, see our Bitcoin and Monero node guide.

Can I host BTCPay Server without KYC?

Yes. BTCPay is software you run yourself, with no account to open, and our hosting needs only an email address and a password, with payment in Bitcoin, Ethereum, Monero, Tether or Solana. Your domain registrar and mail provider have their own rules, and taxes, consumer law and our acceptable use policy still apply.

Does BTCPay Server support Monero?

Yes, through the community-maintained Monero plugin. Set BTCPAYGEN_CRYPTO2="xmr" and run setup again for a pruned Monero node and wallet service, install the plugin under Server Settings > Manage Plugins, and give the store a view-only wallet: primary address, private view key and restore height, never the seed. Follow BTCPay's Monero steps, and plan at least 250 GB of SSD, as its sizing guide advises.

Stuck on a step?

Dedicated and GPU customers can open a ticket from the client area with the server’s IP address and what they tried. First reply target: under 12 hours. For every other server, use the Server actions on its page, the guides and the network status page.

Welcome back

Sign in to manage your servers and your balance.

No KYCHuman check by Cloudflare TurnstileNo tracking