Self-hosted service
btcpayserver/btcpayserver-docker avatar
btcpayserver/btcpayserver-docker

btcpayserver-docker: generating a Bitcoin payment server stack

Docker resources for hosting BTCPayServer easily

761 stars437 forksShellMIT

At a glance

What is it?
The official BTCPay Server Docker repository turns a handful of environment variables into a Compose stack running the payment server, PostgreSQL, NBXplorer, Bitcoin Core, Nginx with automatic certificates and Tor. It is aimed at administrators rather than developers, and the setup script does the heavy lifting.
Who is it for?
btcpayserver-docker suits an administrator who wants a self-hosted BTCPay Server without hand-assembling Compose files for the database, the chain node, the reverse proxy and the certificates, since the generated stack covers the standard Bitcoin deployment in one script. It does not suit a server where a domain and inbound ports 80 and 443 are not available, because the bundled automatic HTTPS depends on both.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the repository actually deploys

This repository contains the official Docker deployment for BTCPay Server. It generates and operates a Docker Compose stack from a small set of environment variables and optional fragments, which is the whole design in one sentence.

The standard Bitcoin deployment includes BTCPay Server itself, PostgreSQL as the database, NBXplorer as the chain explorer and indexer, Bitcoin Core as the node, Nginx with automatic HTTPS certificates, and Tor hidden services with selected Tor connectivity.

That list is worth pausing on, because it explains what this repository is for. A Bitcoin payment server needs a node, a database, a way to track incoming transactions, a reverse proxy that terminates TLS without blocking the user's own certificate, and a privacy option. Each of those is a separate piece of infrastructure that an operator would otherwise have to integrate by hand, and the deployment bundle exists so that the integration is a solved problem rather than a weekend.

Lightning implementations, additional cryptocurrencies and other services are optional, and the architecture guide at docs/architecture.md explains how the components fit together. The optionality is implemented through what the README calls fragments, which are additional Compose fragments merged into the generated stack.

The README is explicit about its audience. If you are still choosing how to host BTCPay Server, start with the deployment overview, and this repository is for administrators who want to run and maintain the Docker deployment.

Before installing: sizing, providers and the domain requirement

Three preparation points come before any command is run, and each one is a gate rather than advice.

The server specifications guide at docs/specs.md is the first, and it exists to select and size a VPS for the chains and features you need. That sizing question is not a detail, since a Bitcoin node with an indexer and a database is a specific CPU, memory and disk profile, and under-provisioning shows up as a synchronisation that never finishes.

The second is the provider list, which the README describes as provider-specific cloud installation guides. It names LunaNode as the most popular, alongside Cloudzy, Clovyr, Microsoft Azure, Google Cloud and Comet Cash.

The third is the domain, and it is the one that most often decides whether the bundled setup works for you. A domain is not required for local or manually proxied deployments. The bundled automatic HTTPS setup, however, requires a domain whose DNS records point to the server and incoming TCP ports 80 and 443 open to the internet. That is the constraint that determines whether you take the automatic certificate path or bring your own reverse proxy, and it is why the deployment has a setting for choosing the reverse proxy.

One more preparation note matters for an existing server. The setup script installs Docker and Docker Compose when needed, and the README asks you to read the installation guide before adapting the process to an existing server, another Linux distribution, or an external reverse proxy.

Running the setup script with the environment variables

The install is a sequence of exported variables followed by one script invocation, run as root from a fresh directory.

bash
sudo su -

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
exit

The variables divide into two families. The plain ones configure the deployment, so BTCPAY_HOST is the domain and NBITCOIN_NETWORK selects mainnet. The BTCPAYGEN_ prefixed ones configure the generator, so BTCPAYGEN_CRYPTO1 declares the first cryptocurrency, BTCPAYGEN_LIGHTNING picks the Lightning implementation and none means no Lightning, BTCPAYGEN_REVERSEPROXY selects nginx, and BTCPAYGEN_ADDITIONAL_FRAGMENTS lists the optional fragments to merge in, in this case opt-save-storage-xs.

The script is invoked with a leading dot so that it runs in the current shell, which is how its exports reach your session, and with the -i flag for the install path. The README describes what happens next: the setup generates the Compose stack, installs the command-line utilities, registers BTCPay Server to start at boot, and starts the services. Initial Bitcoin synchronisation can take time.

After the script finishes, you open the domain in a browser and register the first account, which becomes the server administrator. The README asks you to do that promptly and then follow the synchronisation status in the interface before accepting payments, which is the sensible order since a server that has not synced will not confirm anything.

The helper scripts and what the stack is operated with

The repository root is a set of operational scripts, and their names tell you the shape of running a BTCPay Server this way.

The lifecycle ones are btcpay-up.sh, btcpay-down.sh, btcpay-restart.sh, btcpay-teardown.sh and btcpay-backup.sh, plus btcpay-restore.sh for the other direction. There is btcpay-update.sh, which is the upgrade path, and btcpay-admin.sh for administrative tasks. btcpay-clean.sh suggests a cleanup routine, and btcpay-switch is a separate executable rather than a script, which suggests it is a compiled helper.

Then there are the per-service clients. bitcoin-cli.sh and bitcoin-lightning-cli.sh talk to the node, and bitcoin-lncli.sh is the Lightning one. dash-cli.sh covers Dash, dogecoin-cli.sh, elements-cli.sh, feathercoin-cli.sh, frcli.sh, groestlcoin-cli.sh and groestlcoin-lncli.sh, litecoin-cli.sh, monacoin-cli.sh, monero-wallet-cli.sh, phoenix-cli.sh, litcli.sh and tapcli.sh. beldex-wallet-cli.sh covers the Beldex wallet. There is pihole.sh for the DNS sinkhole, pool.sh, and loop.sh.

Two directories carry the interesting parts. Generated/ holds the output of the generator, which is the Compose stack as it was rendered, and docker-compose-generator/ holds the generator itself. The nginx/ directory holds the reverse proxy configuration, btcpay-fragments holds the optional fragments, Tools/ and contrib/ hold helper tooling, and the docs/ directory holds the documentation the README links to.

The generator is the reason this is a repository with a development guide rather than a shell script. It is code, it has tests in the tests/ directory, and there is a build.sh at the root. The docs/development.md file covers generator internals, testing and adding cryptocurrency support, which is the clearest statement that adding a coin is a supported contribution rather than a fork.

The documentation set and the operating questions it answers

The README's next steps list is a table of contents for running the deployment, and it is worth reading as a statement of what the maintainers consider the hard parts of operating this stack.

Configuring the deployment is docs/configuration.md, choosing a Lightning implementation is docs/lightning.md, and domains, HTTPS, proxies and routes are docs/networking.md. Operating and monitoring the server is docs/operations.md, updating is docs/updating.md, and backing up and restoring is docs/backup-restore.md.

Then there are the four that tell you what the project expects of an operator. docs/fragments.md covers enabling the optional fragments, which is the extension mechanism the environment variable above taps into. docs/customization.md covers customising the generated Compose stack, which is the answer to the question of what happens when the generated file is not exactly right. docs/supported-images.md covers image versions, architectures and source builds, which is where you find out what you are actually pulling. And docs/troubleshooting.md is the first place the support section tells you to look.

The repository also keeps a block of legacy anchors in the README, marked as retained for compatibility with old documentation links, covering the environment variables introduction, the architecture, the generated Docker Compose file, pruning nodes, adding an altcoin, managing optional nginx routes, running on other ports, offloading HTTPS termination, backing up, connecting to the database and upgrading. Those are the questions that were once asked often enough to deserve an anchor, and keeping them means older links from other documentation still land somewhere sensible.

That is a small but telling detail about how this project treats its readers. The documentation is treated as a long-lived surface rather than a rewrite each release.

Where the Docker deployment is the wrong choice

The first limitation is the domain and the open ports. The automatic HTTPS setup requires a domain whose DNS records point at the server and incoming TCP ports 80 and 443 open to the internet. A server behind a restrictive firewall, on a private network, or on a provider that gives you no addressable IP cannot use the bundled path, and while a domain is not required for manually proxied deployments, that is a different configuration with more of your own infrastructure in it.

The second is the network exposure of a node. This deployment runs Bitcoin Core, an indexer and a database on a host that also has a payment interface on it. The Tor hidden services reduce the attack surface of the node, and the README describes the deployment as including selected Tor connectivity, but the chain components still exist on the machine. Operators who need strict separation between the node and the customer-facing application have to design that themselves.

The third is that the generated stack is a starting point, not a finished deployment. The customization documentation exists because the generated Compose file does not fit every situation, and once you edit it you are maintaining a divergence from what the generator would produce on the next update. That is the operational tax of any generated-and-then-hand-edited configuration, and the update documentation is where you find out how the project expects you to handle it.

The fourth is the scope of features. Lightning is set to none in the example, and the standard deployment is Bitcoin only. A merchant who wants Lightning, a second cryptocurrency, or a feature that requires additional services is enabling optional fragments, and each one is a thing that has to be maintained alongside the core stack. The deployment overview is the right starting point precisely because the Docker repository is only one of the possible deployment shapes.

The fifth is operational weight in general. The stack has a database, an indexer, a node, a reverse proxy and a scheduler behind a boot registration, and each of those has a failure mode and an upgrade. A merchant with a low transaction volume is running a lot of infrastructure for the purpose, and a hosted payment processor is a different answer to the same problem.

Licence, maintenance and the cost of running the stack

The deployment files are under the MIT Licence, and the README states that changes are licensed under it. The BTCPay Server application it deploys is a separate project with its own licence, so the two are not the same thing, and the distinction matters for anyone redistributing the arrangement.

The repository is not archived and the last push was on 2026-10-22, so the deployment is actively maintained. It publishes no GitHub releases, which is consistent with a repository whose output is a set of scripts and Compose fragments rather than a versioned artefact, and the image versions live in the supported images documentation and in the generator's configuration rather than in tags.

The CI workflow badge in the README points at a ci.yml workflow, so the generated stack is tested in CI rather than only documented.

The cost of running it is the running cost of the stack itself, which is a node plus an indexer plus a database plus a web server, on hardware you size against the specifications guide. The Tor hidden service adds a little latency to first contact with your own node and reduces its exposure, which is a reasonable default for a payment server that should not advertise where it is.

The cost of operating it is the part the operations documentation is about. Backups have to cover the database and the wallet configuration, updates have to be sequenced so that the node, the indexer and the payment server do not drift apart, and the troubleshooting guide is the first reference the support section points you at. For a merchant with staff, that is a normal infrastructure job. For a single operator, it is a second system to learn, and the community chat at chat.btcpayserver.org is where the answers come from.

Editorial conclusion

btcpayserver-docker suits an administrator who wants a self-hosted BTCPay Server without hand-assembling Compose files for the database, the chain node, the reverse proxy and the certificates, since the generated stack covers the standard Bitcoin deployment in one script. It does not suit a server where a domain and inbound ports 80 and 443 are not available, because the bundled automatic HTTPS depends on both. Read the installation guide before adapting it, and check the supported images documentation for the architectures and versions you intend to run.

Frequently asked questions

What does the btcpayserver-docker deployment include?

The standard Bitcoin deployment includes BTCPay Server, PostgreSQL, NBXplorer, Bitcoin Core, Nginx with automatic HTTPS certificates, and Tor hidden services with selected Tor connectivity. Lightning implementations, additional cryptocurrencies and other services are optional and are added as fragments.

How do I install BTCPay Server with the Docker deployment?

Clone the repository, export the environment variables for your host, network, cryptocurrency, Lightning choice, reverse proxy and fragments, then run the setup script with . ./btcpay-setup.sh -i. The script generates the Compose stack, installs the command-line utilities, registers the server to start at boot and starts the services.

Do I need a domain for the BTCPay Server Docker setup?

Only for the bundled automatic HTTPS. The README says a domain is not required for local or manually proxied deployments, while the automatic certificate setup requires a domain whose DNS records point to the server with incoming TCP ports 80 and 443 open to the internet.

How do I upgrade or customise a generated BTCPay Server Compose stack?

The README points at docs/updating.md for the upgrade path and docs/customization.md for changing the generated stack, with docs/fragments.md covering the optional fragments and docs/supported-images.md listing image versions and architectures. The development guide at docs/development.md covers the generator internals and testing.

Official sources

  1. btcpayserver/btcpayserver-docker on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/btcpayserver-btcpayserver-docker.svg)](https://hysenlabs.com/projects/btcpayserver-btcpayserver-docker)

Was this useful?