Home / Guides / Self-Hosting a BTCPay Server on a VPS
How-to

Self-Hosting a BTCPay Server on a VPS

Run your own BTCPay: direct BTC payments without a processor, what resources it needs, and how a no-KYC VPS removes the onboarding friction.

BitCloudVPS KVM abstract: host split into VM cubes
Short answer

Run your own BTCPay: direct BTC payments without a processor, what resources it needs, and how a no-KYC VPS removes the onboarding friction.

Why self-host BTCPay

BTCPay Server is a free, self-custodial payment processor: invoices are generated by your own node, funds land in your wallet, nobody can freeze or deplatform the checkout. For crypto-native businesses it removes the exact middleman that makes traditional hosting painful.

Business $24/mo (6 vCPU / 16 GB DDR5) is the production size. Crypto invoice, no KYC.

Launch now

Sizing and setup

  1. Business VPS (6 vCPU / 16 GB) is the practical floor for a pruned full node + BTCPay; Pro is comfortable. NVMe matters for initial block download.
  2. The Docker deployment (btcpayserver-docker) is the supported path; prune the node to save disk.
  3. Open 80/443 for the checkout and 8333 for the node; point a domain, get a certificate automatically.
  4. Sync time: pruned initial sync typically takes hours on NVMe, not days.

Notes

What BTCPay actually stores: chain data, NBXplorer and why NVMe decides your week

The direct answer: a BTCPay Server deployment is a Bitcoin full node plus NBXplorer (its wallet indexer), a Postgres database, and the ASP.NET application itself — and of those, only the chain index is large, which is why disk speed and disk size decide both your setup week and your daily invoices. The Bitcoin mainnet chain with default pruning settings, plus NBXplorer's index, is a hundreds-of-gigabytes affair that grows steadily; everything else is small and I/O-light.

This is where plan choice stops being abstract. Every BitCloudVPS plan runs NVMe with ECC RAM, so the random-read pattern of initial block download — millions of small reads at random offsets — lands on flash rather than spinning rust, and IBD completes in days rather than weeks. The 60 GB NVMe on the Starter plan, however, is not enough for an unpruned mainnet archive; you either configure Bitcoin Core with prune=550 (which BTCPay fully supports and which keeps validation trustless — pruned nodes verify every block, they just discard old raw data) or step up to a plan with more storage. ECC matters more than marketing usually admits here: a flipped bit during block validation on non-ECC consumer RAM shows up as the dreaded 'checkpoint mismatch' that forces a full re-download. The other catalog property that matters for a payment server is the port: BTCPay needs sustained outbound connectivity for peer discovery and inbound reachability for incoming peer connections, and the unmetered 1-10 Gbps ports with 1x IPv4 per VPS cover it without traffic anxiety.

BitCloudVPS Business · 240 GB NVMe · unmetered port · $24/mo annual

Deploy in 60 seconds

Sizing the host: where Nano ends, Starter begins, and Business removes the compromises

The direct answer: Nano ($5.49/mo, $36/yr flat) runs BTCPay only with aggressive pruning and only for a low-volume store; Starter (2 vCPU, 4 GB ECC, 60 GB NVMe) is the realistic minimum for a pruned mainnet node with a store or two; Business (6 vCPU, 16 GB ECC, 240 GB NVMe, $30/mo list, $24/mo on the annual term) holds an unpruned chain plus Lightning with room to grow.

Walk the tiers as a payment operator. On Nano, the 4 GB-class memory footprint of the full docker stack — bitcoind, NBXplorer, Postgres, BTCPay, plus a Lightning implementation if you want one — leaves little headroom during IBD, when bitcoind's mempool and index buffers peak; it works, but you are tuning a taut system, and swapping during invoice validation is how a payment server loses trust. Starter's 4 GB ECC with 2 EPYC cores is the documented sweet spot for pruned deployments: IBD on NVMe completes without memory pressure, and steady-state sync uses a fraction of the CPU. The 60 GB disk is the constraint, not the RAM: set prune in the BTCPay environment (BTCPAYGEN_BITCOIN_RPC settings stay default; the prune value lives in the bitcoind docker args) and budget roughly half the disk for chain data plus headroom for growth and backups. Business changes the character of the deployment: 240 GB holds years of unpruned mainnet, 16 GB runs bitcoind + NBXplorer + Core Lightning or LND + Postgres with every buffer comfortable, and if you add a second chain (BTCPay supports altcoin plugins) the headroom is already there. Storage plans ($24-$56/mo, 1-5 TB) exist for archive-scale indexers, not for a store's BTCPay — the compute balance is wrong for the app tier.

Deployment, step by step: from empty Ubuntu box to a live store

The direct answer: the supported path is the official docker-deploy — clone btcpayserver-docker, set two environment variables, run btcpay-setup.sh — and on a fresh VM it takes under thirty minutes of hands-on time, plus IBD wait time that runs unattended.

  1. Deploy the VM with Ubuntu 22.04/24.04, log in as root via SSH, and update: apt update && apt upgrade -y. BitCloudVPS hands you root on a dedicated IPv4, so no cloud-init surprises.
  2. Point a DNS A record at your IPv4 before installing — the setup script provisions HTTPS certificates via Let's Encrypt and refuses to run sensibly without a resolvable hostname.
  3. Clone and configure: git clone https://github.com/btcpayserver/btcpayserver-docker && cd btcpayserver-docker, then export BTCPAY_HOST=pay.yourdomain.org and export NBITCOIN_NETWORK=mainnet. Add BTCPAYGEN_REVERSEPROXY=nginx for the TLS provisioning.
  4. Run . ./btcpay-setup.sh -i. This pulls the container set, generates bitcoind config, and starts everything under docker with a systemd unit so containers return after any host maintenance or your own restart.
  5. Watch IBD honestly: docker logs -f bitcoind, or check progress with docker exec bitcoind bitcoin-cli getblockchaininfo | grep verificationProgress. On NVMe this is the multi-day part — do not interrupt it, and do not 'fix' it by lowering assumed-valid settings you do not understand.
  6. When verificationProgress approaches 1.0, open https://pay.yourdomain.org, register the administrator account, and create your first store. NBXplorer will finish syncing the wallet index shortly after bitcoind completes.

How to verify before showing the checkout to a customer: the server status page (Server Settings → Services) must show Bitcoin and NBXplorer green and 'fully synced', and a test invoice paid from your own wallet must settle from pending to settled at your configured confirmation count.

How to verify the store, wallets and Lightning are actually healthy

The direct answer: a BTCPay deployment is healthy when four independently checkable things are true — the node is fully synced and connected to multiple peers, NBXplorer's index is current, the store's derivation scheme matches the wallet you control, and a round-trip payment settles. Verify each in sequence, not all at once.

  1. Node: docker exec bitcoind bitcoin-cli getblockchaininfo — headers == blocks and verificationProgress near 1; then getpeerinfo should list at least eight outbound peers. If peers hover at one or two, inbound reachability is broken and your node contributes nothing to the network — check the port mapping in the docker setup.
  2. Indexer: in Server Settings → Services, NBXplorer must report 'fully synced'. A lagging index shows up later as invoices that never confirm — the invoice UI waits on NBXplorer, not on bitcoind directly.
  3. Wallet: in the store, confirm the derivation scheme you pasted is the one the watching wallet uses, and that NBXplorer shows tracked addresses incrementing. A mistyped xpub is the classic silent failure: the checkout renders, the address is valid, the coins go to a wallet you cannot sweep. Send $1 of test BTC first. Always.
  4. Lightning (if enabled): docker exec btcpayserver_1-side tools or the UI Lightning page must show the node online with channels open and outbound liquidity. An online node with zero outbound capacity rejects every routed payment — capacity, not uptime, is the health metric.

Then verify from the customer's chair: open the checkout in a private window, pay the test invoice on-chain, and watch it move pending → settled at your confirmation setting. Timestamp the round trip; it is your baseline for every future 'payments are stuck' panic, which almost always turns out to be confirmation count changes, not the server.

Troubleshooting: sync stalls, RPC failures, ports and the invoices that never confirm

The direct answer: BTCPay failures cluster into five patterns — stalled IBD, RPC auth breaks, a full disk, unconfirmed invoices, and certificate expiry. Each has a signature you can recognize in one log glance.

Keep one habit that pays for itself: docker logs before config edits. The overwhelming majority of BTCPay incidents are a container telling you exactly what is wrong, in plain sentences, while someone edits a file based on a forum post from a different deployment style.

Operating it as a business: backups, updates, and keeping the keys exclusively yours

The direct answer: a self-hosted BTCPay is a payment processor you now operate — the keys never leave your server, and that guarantee holds only if you back up the wallet data, keep the stack updated, and never move the hot wallet keys anywhere a second party can subpoena, leak or lose them.

Backups are three artifacts, not one. The store's derivation schemes (the xpubs, and the xpriv backup BTCPay offers at wallet setup — store that offline, encrypted, not on the VPS), the Postgres database (invoices, apps, users — docker exec a pg_dump on a cron to an offsite target), and the Lightning channel state if you run LN (Channel backups change with every channel open/close; the static channel backup must be exported after each change or a restored node cannot reclaim funds). Chain data is the one thing you never back up — it re-syncs from the network by design.

Updates: the docker deployment updates with cd btcpayserver-docker && . ./btcpay-setup.sh -i after a git pull; BTCPay releases a new version every few weeks and the update path is deliberately boring. Schedule it monthly, read the release note for breaking changes, and snapshot the Postgres dump immediately before.

The self-hosting-for-sovereignty argument only lands if the hosting layer matches. Here the checkout is crypto-only across 19 assets with no KYC — signup by token, email optional — so the payment processor and its hosting invoice sit inside the same privacy perimeter: your customers' payment data flows through a server whose own bill is paid in BTC, XMR or USDT, with no card statement connecting the store to a merchant account. Business at $24/mo on the annual term (or quarterly at -10% off the $30 list) is the tier that holds an unpruned chain plus Lightning without compromise, and the same account can run a second instance in another of the 21 locations as a cold spare that your Postgres dump already restores in minutes.

BitCloudVPS Business · BTCPay-ready · $24/mo on the annual term

Deploy in 60 seconds

BTCPay sizing on the VPS sheet

BTCPay Server is really three workloads in one container stack: a full node keeping the chain (BTC at roughly 700 GB and growing), an Electrum-style backend indexing addresses for the store, and the web application handling invoices. That composition drives the sizing honestly: an archive-node deployment belongs on the storage line — 1–5 TB NVMe at $24–$56/mo, with the 2 TB class the practical BTC-only floor — while a pruned-node BTCPay fits a VPS tier if the prune settings are deliberate. The Business tier at $24/mo annual (6 vCPU, 16 GB DDR5 ECC, 240 GB NVMe) runs a pruned BTC node plus Lightning with the index trimmed; Pro at $45 adds room for additional coins' nodes, which BTCPay supports but which multiply the disk bill. ECC memory across the sheet is not decoration for a payments stack — index corruption from a bad bit is the classic silent failure.

The network column matters more than usual for a merchant box. Invoices must load fast at checkout, so rack peering is revenue-adjacent: DE-FRA (~8 ms to AMS on DE-CIX Frankfurt, 100 Gbps) or NL-AMS (under 1 ms, AMS-IX / DE-CIX) for global reach, BR-SAO or SG-SIN for regional storefronts. Unmetered 1–10 Gbps ports mean block syncs and Lightning traffic never appear on a bill. Payment for the host itself closes the loop this page exists for: the checkout takes 19 assets including BTC and XMR, signup is token-based with email optional, and Harborline Node Ltd. of Saint Kitts and Nevis operates the rack — a self-hosted payment processor whose own hosting invoice settles in the coins it processes. The honest maintenance note: BTCPay is a long-running service with real upgrade cadence and channel management if Lightning is on — size the disk for growth, sync on monthly billing first, and take the −20% annual term once the store's first sales have cleared.

Lightning on this sheet: channels, ports, and the operator split

Adding Lightning to a BTCPay deployment changes the profile from storage-and-sync to a networked service with live state, and three specifics matter on this infrastructure. Ports: Lightning needs a reachable TCP port for inbound peers — standard on this sheet, where every VM gets a dedicated IPv4 (plus a /64 IPv6 block that Lightning also speaks), with no NAT in the way. Uptime: channel health is uptime-sensitive, and the network's included DDoS scrubbing plus well-peered racks (CH-ZRH on Tier IV / 2N+1 with a 100 Gbps uplink is the reliability pick) keep a routing node's channels from being forced closed by junk traffic. Disk: channel state and the wallet write frequently, so NVMe everywhere on the sheet is load-bearing rather than marketing.

The operator split deserves its own honesty: BTCPay is self-custodial by design — keys live in your deployment, not the host's — but the host still sees the machine exists and could, in principle, snapshot its disks. That is precisely the situation the no-KYC checkout was built for: the hosting relationship holds a token, an optional email field left empty, and an invoice paid in XMR or any of 19 assets, with Harborline Node Ltd. of Saint Kitts and Nevis as the operator of record — a relationship that cannot be turned into an identity. Combine it with the platform's own discipline (encrypted wallet seeds stored off-box, channel backups exported after every change) and the trust model stays clean: the host provides silicon and route, the merchant keeps custody. Sizing summary for a Lightning-on-BTCPay box: Business annual at $288 covers a pruned mainchain plus a modest routing node; the storage line takes over when the index outgrows prudence. Deploy on monthly billing, prove the sync and the first invoices, then commit a year — the pattern every page on this site recommends, and payments infrastructure more than most.

Where the limits are (October 2026)

Keep the threat model precise. Anonymous-adjacent hosting removes the host-side identity trail: token-only signup, optional email, no KYC review, crypto invoices that record a txid rather than a name. It does not blind the host to traffic it must carry, it does not make a logged-in panel session anonymous, and it does not protect workloads that identify themselves — an admin login from your home IP defeats the whole design. Exact limits of no-KYC anonymity. OPSEC guide. Full checklist. Payment-side note: chain analysis happens on public blockchains, not at the host. Coin choice and network choice are your OPSEC knobs, and the checkout keeps 19 of them open.

What plan should I pick for BTCPay?

Business VPS as the floor, Pro for comfort with Lightning. Storage plans are not the right shape — BTCPay needs CPU and fast small-file NVMe.

Do I need my own domain?

Yes, for the TLS certificate and a sane checkout URL.

Can customers pay in Monero through BTCPay?

Via plugins, yes — though the core BTCPay flow is BTC/Lightning.

Can Starter run a pruned BTCPay mainnet node, or do I need Business?

Starter (2 vCPU, 4 GB ECC, 60 GB NVMe) runs a pruned mainnet deployment for a store or two comfortably — set pruning in the bitcoind args and IBD completes on NVMe without memory pressure. The 60 GB disk makes pruning mandatory. Business (16 GB, 240 GB NVMe) is the tier for an unpruned chain plus Lightning with headroom.

How long does initial block download take on a BitCloudVPS plan?

Initial block download on NVMe-backed plans is a multi-day, unattended process — plan the deployment when you can let the node run for several days. Watch progress with bitcoin-cli getblockchaininfo rather than container logs, and do not interrupt the sync; the wait happens once, and future restarts replay only the delta.

Does the host see my BTCPay wallet or channel keys?

No keys are entered anywhere in the checkout or the panel — BTCPay is self-custodial, so the seeds live only in your deployment and should be backed up off-box. What the operator relationship does contain is visible by design: a token account, an optional email left empty, and an invoice settled in crypto, with Harborline Node Ltd. of Saint Kitts and Nevis as the operator of record. Keep disk encryption and seed discipline on your side and the split holds.

How much disk should a BTCPay node be given?

Plan for growth, not just the current chain: BTC's archive data approaches three figures of gigabytes per year and the Electrum-style index adds its own layer on top. A pruned deployment fits the Business tier's 240 GB NVMe with disciplined settings; an unpruned node plus index wants the 1–2 TB classes on the storage line ($24–$56/mo, up to 5 TB NVMe). All tiers are NVMe with ECC, which matters here: channel state and the address index write constantly.

Why does BTCPay want an unmetered port?

The server stays synced to the chain and relays payments continuously, so a capped plan throttles exactly when customers are checking out. All plans ship unmetered 1-10 Gbps with NVMe and ECC memory, from Starter at $8.50/mo upward.

What does the host actually know about me?

Whatever you hand over: a signup token, an optional email address, the invoice you paid and the service traffic. No ID documents, no phone number, no KYC step exists to hand anything else over.

What won't an anonymous VPS protect against?

Self-inflicted links: personal logins from a home IP, leaked cookies, services that publish your address, and on-chain patterns that tie wallets together. The server removes one identifier; it does not fix operational mistakes.

Ready to launch?

Configure a VPS or dedicated server, set a password, then pay the invoice.

Network

Edge RTT

Uptime · 36h

Complaints · 36h

Pick a city