diff --git a/Production-NoReverseProxy/README.md b/Production-NoReverseProxy/README.md index 25de599..eb2ec15 100644 --- a/Production-NoReverseProxy/README.md +++ b/Production-NoReverseProxy/README.md @@ -1,6 +1,6 @@ # About those pre-generated docker-compose -All `docker-compose` files in this folder are generated by running the [build-pregen.sh](build-pregen.sh) (or [build-pregen.ps1](build-pregen.ps1)) script from the fragments located in [docker-compose-generator/docker-fragments](docker-compose-generator/docker-fragments). +All `docker-compose` files in [Production](Production), [Production-NoReverseProxy](Production-NoReverseProxy) and [Production-Traefik](Production-Traefik) are generated by running the [build-pregen.sh](build-pregen.sh) (or [build-pregen.ps1](build-pregen.ps1)) script from the fragments located in [docker-compose-generator/docker-fragments](docker-compose-generator/docker-fragments). The pre-generated `docker-compose` files only cover `btc`, `ltc`, `clightning` without reverse proxy. diff --git a/Production-Traefik/Production.png b/Production-Traefik/Production.png new file mode 100644 index 0000000..6a27ef0 Binary files /dev/null and b/Production-Traefik/Production.png differ diff --git a/Production-Traefik/README.md b/Production-Traefik/README.md new file mode 100644 index 0000000..2ef4dc2 --- /dev/null +++ b/Production-Traefik/README.md @@ -0,0 +1,73 @@ +# About those docker-compose + +All `docker-compose` files in [Production](Production), [Production-NoReverseProxy](Production-NoReverseProxy) and [Production-Traefik](Production-Traefik) are generated by running the [build-pregen.sh](build-pregen.sh) (or [build-pregen.ps1](build-pregen.ps1)) script from the fragments located in [docker-compose-generator/docker-fragments](docker-compose-generator/docker-fragments). + +The pre-generated `docker-compose` files only cover `btc`, `ltc`, `clightning` with `traefik`. + +--- + +We strongly advise you to not use the pre-generated docker-compose of this folder, they are deprecated and kept only for backward compatibility. +Instead use the [build.sh](../build.sh) as documented in (README)(../Readme.md) to generate a docker-compose which fit your needs. + +--- + +The `docker-compose` can be used for production purpose. + +It is composed of: + +1. One full node per supported cryptocurrency (bitcoind/litecoind) +2. A lightweight block explorer ([NBxplorer](https://github.com/dgarage/NBXplorer)) +3. A [BTCPay Server](https://github.com/btcpayserver/btcpayserver) +4. A database (Postgres) +5. A reverse proxy (Traefik) xontainer that also handles SSL certificate renewal + +![Architecture](Production.png) + +[The Deploy on Azure Button](https://github.com/btcpayserver/btcpayserver-azure) is using this `docker-compose` under the hood on an Ubuntu machine. You can use it on any docker supporting host. + +The relevant environment variables are: + +* `NBITCOIN_NETWORK`: The blockchain identifier used by NBitcoin (eg., `regtest`, `testnet`, `mainnet`) +* `BTCPAY_HOST`: The external url used to access the NGINX server from internet. This domain name must point to this machine for Let's Encrypt to create your certificate. (typically with a CNAME or A record) +* `BTCPAY_ROOTPATH`: The root path directory where BTCPay is accessed, more information below. (default: /) +* `LETSENCRYPT_EMAIL`: The email Let's Encrypt will use to notify you about certificate expiration. +* `LIGHTNING_ALIAS`: Optional, if using the integrated lightning feature, customize the alias of your nodes +* `BTCPAY_SSHKEYFILE`: Optional, SSH private key that BTCPay can use to connect to this VM's SSH server (You need to copy the key file on BTCPay's datadir volume) +* `BTCPAY_SSHTRUSTEDFINGERPRINTS`: Optional, BTCPay will ensure that it is connecting to the expected SSH server by checking the host public's key against those fingerprints + +If `BTCPAY_HOST` is `btcpay.example.com` and `BTCPAY_ROOTPATH` is `/btcpay`, then you can access the site via `https://btcpay.example.com/btcpay` + +Use `docker-compose.btc-ltc.yml` for bitcoin and litecoin support, or `docker-compose.btc.yml` for only bitcoin. + +Any unset or empty environment variable will be set for a `regtest` deployment. + +The ports mapped on the host are: + +1. `80` for Let's encrypt +2. `443` for the website +3. `9735` for the bitcoin lightning network node (if used) +4. `9736` for the litecoin lightning network node (if used) + +Example for running on `mainnet`: + +For linux: + +``` +docker-compose up \ + -e "NBITCOIN_NETWORK=mainnet" \ + -e "BTCPAY_HOST=btcpay.example.com" \ + -e "LETSENCRYPT_EMAIL=me@example.com" +``` + +For powershell: + +``` +docker-compose up ` + -e "NBITCOIN_NETWORK=mainnet" ` + -e "BTCPAY_HOST=btcpay.example.com" ` + -e "LETSENCRYPT_EMAIL=me@example.com" +``` + +See also [The guide for docker noobs](../README.md#fornoobs). + +Make sure the domain `btcpay.example.com` point to your server and that port `80` and `443` are open. \ No newline at end of file diff --git a/Production-Traefik/traefik.toml b/Production-Traefik/traefik.toml new file mode 100644 index 0000000..e54e954 --- /dev/null +++ b/Production-Traefik/traefik.toml @@ -0,0 +1,35 @@ +defaultEntryPoints = ["https","http"] + +logLevel = "ERROR" + +[entryPoints] + useXForwardedFor = true + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + +[retry] + +[docker] +endpoint = "unix:///var/run/docker.sock" +watch = true +exposedByDefault = false + +[acme] +storage = "acme.json" +entryPoint = "https" +onHostRule = true +[acme.httpChallenge] +entryPoint = "http" + +[traefikLog] + filePath = "/traefik_logs/traefik.log" + format = "json" + +[accessLog] + filePath = "/traefik_logs/access.log" + format = "json" diff --git a/build-pregen.ps1 b/build-pregen.ps1 index b8faf78..0c1ce52 100755 --- a/build-pregen.ps1 +++ b/build-pregen.ps1 @@ -3,5 +3,6 @@ docker pull btcpayserver/docker-compose-generator docker run -v "$(Get-Location)\Production:/app/Production" ` -v "$(Get-Location)\Production-NoReverseProxy:/app/Production-NoReverseProxy" ` + -v "$(Get-Location)\Production-Traefik:/app/Production-Traefik" ` -v "$(Get-Location)\docker-compose-generator\docker-fragments:/app/docker-fragments" ` --rm btcpayserver/docker-compose-generator pregen \ No newline at end of file diff --git a/build-pregen.sh b/build-pregen.sh index 27fe54c..f430474 100755 --- a/build-pregen.sh +++ b/build-pregen.sh @@ -4,5 +4,6 @@ docker pull btcpayserver/docker-compose-generator docker run -v "$(pwd)/Production:/app/Production" \ -v "$(pwd)/Production-NoReverseProxy:/app/Production-NoReverseProxy" \ + -v "$(pwd)/Production-Traefik:/app/Production-Traefik" \ -v "$(pwd)/docker-compose-generator/docker-fragments:/app/docker-fragments" \ --rm btcpayserver/docker-compose-generator pregen diff --git a/build.ps1 b/build.ps1 index 2eb4277..23ddca3 100755 --- a/build.ps1 +++ b/build.ps1 @@ -23,5 +23,5 @@ If ($BTCPAYGEN_REVERSEPROXY -eq "nginx") { } If ($BTCPAYGEN_REVERSEPROXY -eq "traefik") { - Copy-Item ".\Production\traefik.toml" -Destination ".\Generated" + Copy-Item ".\Production-Traefik\traefik.toml" -Destination ".\Generated" } diff --git a/build.sh b/build.sh index bc66030..d86749e 100755 --- a/build.sh +++ b/build.sh @@ -24,7 +24,7 @@ if [ "$BTCPAYGEN_REVERSEPROXY" == "nginx" ]; then fi if [ "$BTCPAYGEN_REVERSEPROXY" == "traefik" ]; then - cp Production/traefik.toml Generated/traefik.toml + cp Production-Traefik/traefik.toml Generated/traefik.toml fi diff --git a/docker-compose-generator/docker-fragments/btcpayserver-nginx.yml b/docker-compose-generator/docker-fragments/btcpayserver-nginx.yml new file mode 100644 index 0000000..366353a --- /dev/null +++ b/docker-compose-generator/docker-fragments/btcpayserver-nginx.yml @@ -0,0 +1,15 @@ +version: "3" + +services: + + btcpayserver: + environment: + # NGINX settings + VIRTUAL_NETWORK: nginx-proxy + VIRTUAL_PORT: 49392 + VIRTUAL_HOST: ${BTCPAY_HOST} + SSL_POLICY: Mozilla-Modern + + # Let's encrypt settings + LETSENCRYPT_HOST: ${BTCPAY_HOST} + LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL:-} \ No newline at end of file diff --git a/docker-compose-generator/docker-fragments/btcpayserver.yml b/docker-compose-generator/docker-fragments/btcpayserver.yml index 2cf8a8c..7425cc5 100644 --- a/docker-compose-generator/docker-fragments/btcpayserver.yml +++ b/docker-compose-generator/docker-fragments/btcpayserver.yml @@ -16,16 +16,6 @@ services: BTCPAY_ROOTPATH: ${BTCPAY_ROOTPATH:-/} BTCPAY_SSHTRUSTEDFINGERPRINTS: ${BTCPAY_SSHTRUSTEDFINGERPRINTS} BTCPAY_SSHKEYFILE: ${BTCPAY_SSHKEYFILE} - - # NGINX settings - VIRTUAL_NETWORK: nginx-proxy - VIRTUAL_PORT: 49392 - VIRTUAL_HOST: ${BTCPAY_HOST} - SSL_POLICY: Mozilla-Modern - - # Let's encrypt settings - LETSENCRYPT_HOST: ${BTCPAY_HOST} - LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL:-} links: - nbxplorer @@ -34,24 +24,5 @@ services: - "btcpay_datadir:/datadir" - "nbxplorer_datadir:/root/.nbxplorer" - nbxplorer: - restart: unless-stopped - image: nicolasdorier/nbxplorer:1.0.2.31 - expose: - - "32838" - environment: - NBXPLORER_NETWORK: ${NBITCOIN_NETWORK:-regtest} - NBXPLORER_BIND: 0.0.0.0:32838 - volumes: - - "nbxplorer_datadir:/datadir" - - postgres: - restart: unless-stopped - image: postgres:9.6.5 - volumes: - - "postgres_datadir:/var/lib/postgresql/data" - volumes: - postgres_datadir: - btcpay_datadir: - nbxplorer_datadir: \ No newline at end of file + btcpay_datadir: \ No newline at end of file diff --git a/docker-compose-generator/docker-fragments/nbxplorer.yml b/docker-compose-generator/docker-fragments/nbxplorer.yml new file mode 100644 index 0000000..4edc651 --- /dev/null +++ b/docker-compose-generator/docker-fragments/nbxplorer.yml @@ -0,0 +1,17 @@ +version: "3" + +services: + + nbxplorer: + restart: unless-stopped + image: nicolasdorier/nbxplorer:1.0.2.31 + expose: + - "32838" + environment: + NBXPLORER_NETWORK: ${NBITCOIN_NETWORK:-regtest} + NBXPLORER_BIND: 0.0.0.0:32838 + volumes: + - "nbxplorer_datadir:/datadir" + +volumes: + nbxplorer_datadir: \ No newline at end of file diff --git a/docker-compose-generator/docker-fragments/postgres.yml b/docker-compose-generator/docker-fragments/postgres.yml new file mode 100644 index 0000000..d558564 --- /dev/null +++ b/docker-compose-generator/docker-fragments/postgres.yml @@ -0,0 +1,11 @@ +version: "3" + +services: + postgres: + restart: unless-stopped + image: postgres:9.6.5 + volumes: + - "postgres_datadir:/var/lib/postgresql/data" + +volumes: + postgres_datadir: \ No newline at end of file diff --git a/docker-compose-generator/src/DockerComposition.cs b/docker-compose-generator/src/DockerComposition.cs index 65f4256..b9c8f9d 100644 --- a/docker-compose-generator/src/DockerComposition.cs +++ b/docker-compose-generator/src/DockerComposition.cs @@ -42,15 +42,6 @@ namespace DockerGenerator composition.SelectedProxy = (Environment.GetEnvironmentVariable("BTCPAYGEN_REVERSEPROXY") ?? "").ToLowerInvariant(); composition.SelectedLN = (Environment.GetEnvironmentVariable("BTCPAYGEN_LIGHTNING") ?? "").ToLowerInvariant(); composition.AdditionalFragments = (Environment.GetEnvironmentVariable("BTCPAYGEN_ADDITIONAL_FRAGMENTS") ?? "").ToLowerInvariant().Split(';').Where(t => !string.IsNullOrWhiteSpace(t)).ToArray(); - if (composition.SelectedProxy == "traefik" && !composition.AdditionalFragments.Contains("traefik-labels")) - { - var additionalFragments = new List(); - additionalFragments.AddRange(composition.AdditionalFragments); - additionalFragments.Add("traefik-labels"); - - composition.AdditionalFragments = additionalFragments.ToArray(); - } - return composition; } } diff --git a/docker-compose-generator/src/Program.cs b/docker-compose-generator/src/Program.cs index 07fbb35..a62987f 100644 --- a/docker-compose-generator/src/Program.cs +++ b/docker-compose-generator/src/Program.cs @@ -8,18 +8,21 @@ namespace DockerGenerator { class Program { - static void Main(string[] args) { var root = Environment.GetEnvironmentVariable("INSIDE_CONTAINER") == "1" ? FindRoot("app") : Path.GetFullPath(Path.Combine(FindRoot("docker-compose-generator"), "..")); - + + Dictionary ProxyMapping = new Dictionary() + { + {"nginx", Path.GetFullPath(Path.Combine(root, "Production"))}, + {"no-reverseproxy", Path.GetFullPath(Path.Combine(root, "Production-NoReverseProxy"))}, + {"traefik", Path.GetFullPath(Path.Combine(root, "Production-Traefik"))} + }; if(args.Any(a => a == "pregen")) { - var productionLocation = Path.GetFullPath(Path.Combine(root, "Production")); - var testLocation = Path.GetFullPath(Path.Combine(root, "Production-NoReverseProxy")); - foreach(var proxy in new[] { "nginx", "no-reverseproxy", "traefik" }) + foreach(var proxy in ProxyMapping.Keys) { foreach(var lightning in new[] { "clightning", "" }) { @@ -40,11 +43,7 @@ namespace DockerGenerator composition.SelectedCryptos.Add(ltc); composition.SelectedLN = lightning; composition.SelectedProxy = proxy; - if (composition.SelectedProxy == "traefik") - { - composition.AdditionalFragments = new []{"traefik-labels"}; - } - new Program().Run(composition, name, new string[] {"nginx", "traefik"}.Contains(proxy)? productionLocation : testLocation); + new Program().Run(composition, name, ProxyMapping[proxy]); } } } @@ -76,15 +75,19 @@ namespace DockerGenerator case "nginx": fragments.Add("nginx"); + fragments.Add("btcpayserver-nginx"); break; case "traefik": fragments.Add("traefik"); + fragments.Add("traefik-labels"); break; case "no-reverseproxy": fragments.Add("btcpayserver-noreverseproxy"); break; } fragments.Add("btcpayserver"); + fragments.Add("nbxplorer"); + fragments.Add("postgres"); foreach(var crypto in CryptoDefinition.GetDefinitions()) { if(!composition.SelectedCryptos.Contains(crypto.Crypto))