TUTORIALS
How to accept Bitcoin payments yourself with BTCPay Server
Every hosted payment processor is a company that can freeze you. That is not a hypothetical for anyone taking Bitcoin: the large processors added identity verification, payout thresholds and settlement rules years ago, and a merchant who fails one of those checks usually finds out with money already in flight. BTCPay Server exists because of exactly that. It is free, open-source software that turns a server you control into your own checkout — invoices, a point-of-sale screen, store plugins, Lightning — with no company in the middle, no percentage taken and no account to lose. Installing it is genuinely a single afternoon. What decides whether the result is any good is the machine underneath it, and the handful of details a default installation quietly leaves pointing back at you.
What BTCPay Server actually replaces
A hosted processor sits between your customer and your wallet. It generates the address, watches the chain, converts the amount, holds the funds for some period and eventually pays you out. Every one of those steps is something it learns about you and a point at which it can decline. BTCPay does the same work on hardware you rent, and the difference in what it knows is total.
- Payments land directly in your own wallet. You give BTCPay an extended public key, it derives a fresh address per invoice and watches for it — it never holds a private key for on-chain payments and cannot move a satoshi.
- There is no fee and no account. The software is open source, you run it yourself, and there is nothing to apply for and nothing to be suspended from.
- It handles the parts that are tedious to build: invoice expiry, live rate conversion, underpayments and overpayments, partial payments, refunds and a receipt the customer can verify independently.
- It ships the front ends most people need — a point-of-sale screen, pay buttons, a crowdfunding page, plugins for the usual e-commerce platforms — and a full API if you are wiring it into your own software.
- Lightning comes in the same deployment if you want it, which is what makes payments below a few dollars viable at all.
The boundary is worth stating plainly. BTCPay does not turn Bitcoin into your local currency, and it does not remove the exchange or the bank if that is where the money eventually has to go. What it removes is the processor — the intermediary that took a cut, held your funds in between and required your identity to do it. What you get back has the same shape as a website you host yourself: more control, and the work that comes with it.
You become the payment processor
That work is the honest cost of self-hosting, and it is much better understood before the install than after. Nobody watches your uptime, nobody restores your backup, and nobody is on the other end of a support line at the moment a customer insists they paid and you cannot see it.
- Uptime is yours. An invoice cannot be created while the server is down, so a checkout that must always work needs a machine somebody actually monitors.
- Backups are yours. Losing the server is survivable; losing the wallet descriptor or the Lightning channel state is not.
- Key custody splits in two. On-chain funds sit in a wallet BTCPay only watches, which is the safe arrangement. Lightning funds sit in a hot wallet on the server itself, which is not — treat that balance as float, never as savings.
- Disputes have no arbiter. There are no chargebacks, which is largely the point, but it also means every refund is a decision you make and a transaction you send.
- Updates are yours. Underneath the friendly interface is a stack of containers with a Bitcoin node in it, and it needs the same maintenance discipline as anything else left running on a public IP.
None of that is heavy. It is a few minutes a month once the thing is running, plus one careful afternoon at the start. It is simply not zero, and a processor fee was partly buying you exactly this.
Sizing the machine: the node underneath decides everything
BTCPay itself is a light application. The Bitcoin node it runs against is not, and nearly every sizing mistake here comes from budgeting for the web app rather than for the chain beneath it. A standard deployment brings up Bitcoin Core, an indexer that tracks your wallets, a database, a reverse proxy and the application — and it is Core that wants the disk, the memory and the patience.
- Storage is the decision that picks your plan. An unpruned chain is past 750 GB today and grows by roughly 7 GB a month. The deployment ships storage-saving presets that cap block data at roughly 100, 50 or 25 GB instead, and every one of them is still a real full node that verifies every rule for itself.
- Pruning does not shorten the first sync. Core downloads and checks every block since genesis either way; pruning only decides what it keeps afterwards.
- Memory is where sync speed comes from. 4 GB runs it, 8 GB syncs noticeably faster and leaves room for Lightning and a database that is not fighting the node for cache.
- NVMe is not optional. The initial sync is dominated by random reads and writes against the UTXO database, so the same job on a slow disk takes days rather than hours.
- Bandwidth is unremarkable once you are synced, but the first sync pulls the entire chain. A metered plan is the wrong shape for that.
In practice that lands on VPS-8 at $13.99/mo — 4 vCPU EPYC, 8 GB DDR5 ECC and 120 GB of Gen4 NVMe — as the sensible default for a pruned node with Lightning, with VPS-16 at $26.99/mo if you would rather never think about the disk again. Every VPS tier ships Gen4 NVMe in RAID-10 and unmetered transfer, so capacity is the only real variable. If you want the chain unpruned — to rescan an old wallet, or to run an Electrum server beside the store — skip the VPS range entirely: a dedicated server from $64/mo with 2 × 1 TB NVMe is both cheaper and far roomier than the largest VPS, and the arithmetic only gets worse with time. The trade-offs are the same ones covered in running a Bitcoin full node, because that is precisely what you are doing here with a checkout bolted on top.
Step by step: from a fresh VPS to a live checkout
- 01Deploy the VPS and harden it firstA Debian or Ubuntu box, keys-only SSH, default-deny firewall — before anything valuable is on it. The ordered version of that checklist is its own guide.
- 02Point a domain at the server and open 80 and 443BTCPay issues its own certificate on first start, which only works if the hostname already resolves to the machine and both ports are reachable. Getting this backwards is the most common failed install by a wide margin.
- 03Clone the official Docker deploymentThe project ships an opinionated container setup. Use it rather than assembling the pieces by hand — it is what the upgrade path is tested against.
- 04Decide your options before the first runNetwork, host name, Lightning implementation and storage preset are environment variables read once at setup. Changing the pruning level afterwards is not free, so choose now.
- 05Run the setup script and let it syncEverything comes up in containers and Bitcoin Core begins its initial block download. This is the long part — several hours on NVMe — and the one step you cannot hurry.
- 06Register the admin account immediatelyThe first account to sign up becomes the administrator. Do it the moment the interface answers, not the next morning.
- 07Attach a wallet to your storeCreate a store, then connect a wallet by importing an extended public key from a hardware wallet or a dedicated account in your own software. BTCPay watches the addresses; it never signs anything.
- 08Test with a real payment, then wire up the front endSend yourself a small amount and confirm the invoice settles. Only then connect the point-of-sale screen, the store plugin or the API your site will actually call.
Lightning: worth it, and what it actually costs
On-chain payments work everywhere and cost whatever the mempool costs that day, which makes anything under a few dollars awkward and sometimes absurd. Lightning fixes that, and BTCPay will bring up a node for you in the same deployment. For small or frequent payments it is the right answer. It is also an operational commitment of a different kind from a Bitcoin node, and the differences are worth knowing before you switch it on.
- You need inbound liquidity before you can be paid. Opening your own channel gives you capacity to spend, not to receive. Until someone opens a channel toward you or you acquire inbound capacity, your node cannot accept anything at all.
- The balance is hot by design. Channel funds live in a wallet on the server, online because they have to be. Keep working float there and sweep the rest on-chain.
- Channel state is not backed up by copying files. Restoring an old snapshot of a Lightning node can cost you the channels it describes. Use the implementation's own backup mechanism and understand what it actually restores.
- Downtime costs more here than on-chain. An offline node cannot route or receive, and a stale state that comes back online can be penalised.
- Channels have on-chain costs at both ends. Opening and closing are transactions, so a habit of many small channels is quietly expensive.
- Your node is visible if you let it be. A publicly announced node broadcasts its alias and network address to everyone, which puts your server on a map anybody can read.
A sensible middle path is Lightning with unannounced channels — you can be paid without publishing your infrastructure — and on-chain as the default for anything large. If you want the node reachable without being attributable, run it over Tor, the same reasoning that puts a Bitcoin node behind an onion service instead of a public IP.
The identity leaks a default install leaves in place
This is the section that matters if you chose BTCPay specifically to escape a processor that knew who you were. The software removes that processor perfectly. It does not, on its own, remove everything else that ties the checkout to a person — and most of those come from steps that feel unrelated to payments.
- The domain. A registrar holds your identity even when public WHOIS is redacted, and it needs a working address to keep the name alive. The hostname is the single most common way a self-hosted checkout is traced back to its owner.
- Certificate transparency. The moment a certificate is issued, the exact hostname is published in public logs anyone can search. A subdomain you assumed was private — pay.something, btcpay.something — is announced worldwide with a timestamp on it.
- The host. If the server was bought with a card in your legal name, the machine is in your legal name no matter what runs on it. That is settled at signup, long before the first invoice.
- The extended public key. Handing BTCPay an xpub lets it watch every address that key derives, including balances and history you never meant to expose to a web application. Use a dedicated account for the store, never the xpub of your main wallet.
- The Lightning node. An announced node publishes an alias and an address. An alias carrying your brand, on an IP that also serves your checkout, links the two together permanently in a public graph.
- Outbound calls. Rate providers, plugins and notification integrations all reach out from the machine, and email notifications travel through whatever SMTP account you configured. Each one is a third party that sees your server.
- The payout path. Coins that leave the store for a verified exchange account arrive with their history attached. That leak is downstream of BTCPay, and it is the one that most often undoes all the care taken upstream.
Closing those is ordinary work rather than anything exotic. Pick a registrar that accepts crypto and collects the minimum, and give it an address that is not tied to your identity. Put the machine on a host that never asked who you are and pay for it from a crypto balance — Bitcoin is pseudonymous rather than anonymous, so topping up in Monero is what closes the on-chain trail if that matters to you. And reach the admin interface over a WireGuard tunnel instead of exposing a login page for something that holds money. Each is a small decision made once; together they are the difference between "no processor" and genuinely private.
Keeping it alive after launch
A checkout that has worked for a year is a checkout nobody has looked at for a year. A short maintenance routine is what keeps that from turning into an outage on your busiest day.
- Update on the project's cadence, not your own. The deployment has an upgrade path that moves matched container versions together; bumping pieces by hand is how a working stack becomes a broken one.
- Back up what cannot be regenerated: the store database and configuration, the wallet descriptor, and the Lightning backup if you run one. The blockchain is not a backup — it re-downloads.
- Restore once, deliberately, while nothing is wrong. An untested backup of a payment system is a hypothesis about your revenue.
- Watch the disk. A pruned node has a stable footprint, but logs and databases do not, and a full disk stops the node, which stops the invoices.
- Keep the machine patched and the ports closed. Everything on the first-ten-minutes hardening checklist applies here, with rather more at stake.
Add an external check on the store while you are at it. Something as simple as a monitor hitting the invoice endpoint from outside tells you the checkout is down before a customer does, which is most of the practical difference between self-hosting and being unreachable. And treat the box itself the way the first ten minutes on a new VPS describes, because the stakes are higher on a machine that holds money.
Mistakes that cost real money
- Importing a seed phrase instead of an extended public key, turning a public web application into a hot wallet holding every payment ever received.
- Configuring DNS after running the installer, then wondering why the certificate never issued and the site will not load.
- Choosing the most aggressive pruning preset, then trying to attach a wallet with years of history the node can no longer rescan.
- Treating the Lightning balance as savings rather than as float that happens to live online.
- Backing up a Lightning node by copying its data directory and assuming that is a restore path.
- Buying a plan sized for the web application and running out of disk halfway through the initial sync.
- Leaving the admin interface open to the whole internet behind a password reused from somewhere else.
- Registering the domain and renting the server in your own name, after doing everything else right.
BTCPay is one of the few pieces of software that removes an intermediary outright instead of replacing it with a friendlier one. The install is an afternoon and the sync is a night. What you are left with is a checkout that takes Bitcoin and Lightning, charges nothing, custodies nothing, and answers to nobody — running on a machine you can pay for out of the same balance it collects. Size the disk for the node, keep the seed off the server, and put the box somewhere that never asked for your name.