Pick the smallest checkout surface that fits what you already have. A payment request is a link you send someone — no website required, and the fastest way to invoice a client. A point of sale app turns the same instance into a till with a product list, which works from a phone at a market stall. A pay button is a snippet of HTML for a static site. A shop plugin adds Bitcoin as a payment method to a real storefront and writes the order status back automatically. And the REST API issues invoices, reports their state and calls a webhook when one settles, which is the integration that ages best because it depends on nothing but HTTP and a shared secret.
Whichever you choose, wire the webhook and then test that it fires. An invoice that settles and never notifies your application is the failure mode nobody catches, because everything looks correct on both sides in isolation: the money arrived, the customer saw a confirmation page, and the order sits unfulfilled. Send yourself a settled-invoice webhook on purpose, confirm your endpoint received it, and verify the signature rather than trusting the payload — that endpoint is public and anyone can post to it.
A nightly backup is not a Lightning restore path
This is the one warning on this page that can cost you money rather than time, and the project's own documentation states it in the same words: old Lightning channel state is toxic. Restoring last night's copy of a channel database and letting the node run means broadcasting a state your counterparty has already superseded — which the protocol treats as an attempted cheat and punishes by awarding them the whole channel balance. So the archive is right for the store database, the configuration and the invoice history, and it is not a recovery plan for channels. Copy the static channel backup off the machine continuously, keep the newest one, and if you ever restore a whole server from an archive, do it knowing the Lightning side needs the documented recovery procedure rather than a straight restore.
With that understood, the routine is short. The deployment ships a backup script that archives the volumes and dumps the database while skipping the blockchain data, and it accepts a passphrase so the archive is encrypted before it leaves the box. Run it on a timer, then push the result to a machine in a different jurisdiction the way the backups guide describes — an append-only repository is worth the extra ten minutes here, because a compromised payment server should not be able to erase the record of what it processed.
cd ~/BTCPayServer/btcpayserver-docker
export BTCPAY_BACKUP_PASSPHRASE="a long passphrase you keep elsewhere"
./btcpay-backup.sh # archives volumes + database, skips the chain
# then ship the archive offsite, and keep the channel backup separately
Upgrades come next, and a payment box is the one machine where "update it later, on purpose" is the correct policy. The deployment has its own update script that regenerates the compose file and pulls the new images; run it when you have read the release notes, not when a cron job feels like it. Take the archive first. Bump one release at a time. And keep the previous version written down, because a rollback you can do in a minute is what makes the whole thing low-stakes.
./btcpay-update.sh # deliberate, after reading the release notes
df -h / # the check that should be an alert, not a habit
Finally, set one alert and one reminder. The alert is on disk usage — a blockchain node is the one process on the machine that grows on its own, and a full volume takes the checkout down in a way that is slow to diagnose because nothing else changed. Fire it at eighty per cent, not ninety-five. The reminder is monthly, and it is to open the store and look at two things: that invoices are still settling, and that the Lightning channels you opened are still alive. A payment processor fails quietly, and the way you find out is a customer telling you they could not pay.