Every payment processor in the middle comes with its own terms, its own KYC and its own button that freezes your balance. BTCPay Server removes the middle. Invoices are created on your server, the customer pays to an address derived from your wallet, and your own Bitcoin node confirms the payment. Nobody can switch it off but you.
It's for shops, freelancers and services that already take bitcoin — or want to — and would rather not hand that job to a company.
Which plan
BTCPay runs as about seven containers: the BTCPay app, NBXplorer (which watches the chain), Bitcoin Core, Postgres and an nginx front with automatic Let's Encrypt. On our test server they used around 0.7 GB of RAM at the start, and Bitcoin Core takes more while it syncs; 4 GB is plenty. Disk is the real constraint, not memory.
| Setup | Plan |
|---|---|
| On-chain BTC, pruned node keeping ~5 GB of blocks | Small-IP — 4 vCPU, 4 GB, 35 GB ($16/mo) |
| Same, with more breathing room for logs and updates | Medium-IP — 6 vCPU, 6 GB, 45 GB ($20/mo) |
| Lightning, a bigger block window, or a second coin | Pro-32 — 8 vCPU, 32 GB, 400 GB ($40/mo), on request |
You need a plan with its own IPv4: customers reach BTCPay over HTTPS, and Let's Encrypt has to reach port 80. Choose Germany or Finland, whichever is available at checkout — for a payment page, latency hardly matters. And since the whole point is taking crypto, it's fitting that the server itself is paid in crypto without KYC.
Install
Point pay.example.com at the server, then, as root on a fresh Ubuntu 24.04 or Debian 12:
mkdir BTCPayServer && cd BTCPayServer
git clone https://github.com/btcpayserver/btcpayserver-docker
cd btcpayserver-docker
export BTCPAY_HOST="pay.example.com"
export LETSENCRYPT_EMAIL="you@yourdomain.com"
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-xxs"
export BTCPAYGEN_REVERSEPROXY="nginx"
export BTCPAYGEN_LIGHTNING="none"
. ./btcpay-setup.sh -i
opt-save-storage-xxs is what makes it fit: Bitcoin Core prunes down to 5 GB of blocks. The script pulls the images, creates a btcpayserver systemd service and starts everything. It also restarts the Docker daemon on the way — one more reason to give BTCPay a server of its own rather than squeezing it next to other containers.
Check the node:
bitcoin-cli.sh getblockchaininfo
Look at blocks against headers, and at "pruned": true. Twenty minutes into our test it had about 218,000 of roughly 972,000 blocks — the early ones are tiny, so don't extrapolate from that. The real work comes later.
First login: do it now
Open https://pay.example.com the moment it answers. BTCPay sends you to a registration page, and the first account becomes the server admin. If someone else finds the page before you do, they own your payment server. Register, then look under Server Settings → Policies and make sure new sign-ups are the way you want them.
Then create a store and connect your wallet with its extended public key (xpub) — from a hardware wallet or your desktop wallet's export. BTCPay derives a fresh address for every invoice and never sees a private key. Use a fresh wallet or a fresh account for this rather than one with years of history behind it: a pruned node is happiest tracking what happens from now on.
Until the node catches up, BTCPay shows that it's still synchronizing and won't watch for payments. Plan the launch for after the sync, not for the evening you install it.
Things you should know before going live
- The first sync is long. A pruned node still downloads and verifies the entire chain — more than 700 GB — before it can throw old blocks away. Traffic on our plans is unmetered at 1 Gbit/s, so it costs nothing extra, but on a 4-vCPU server think in days. There's a fast-sync script in the repository; it skips that work by trusting someone else's copy of the UTXO set, which defeats part of the reason you're running a node.
- Updates.
btcpay-update.shpulls the latest BTCPay and its dependencies. Run it in a quiet hour, not during a sale. - What to back up. With an xpub-only wallet your coins aren't on the server. What you'd lose is the store setup and invoice history in Postgres — back up that volume, and keep your wallet's seed somewhere that has nothing to do with this server.
- Lightning later. Start on-chain. Lightning means a bigger block window, channel management and inbound liquidity — a project of its own, and a Pro plan, which we set up on request.
My take: for a small shop that takes bitcoin once a day, BTCPay on Small-IP is the cleanest setup there is. If you need card payments or fiat payouts, this isn't that tool.
Related
- Run your own Bitcoin node on a VPS — the node on its own, if you only want to verify your wallet
- Run your own Monero node on a VPS
- Crypto VPS — paying for servers in crypto
- VPS for a website on your own IP — the shop that sends customers to BTCPay
- How to configure a ufw firewall
Comments
No comments yet. Be the first.