btcpayserver / btcpayserver-docker

Docker resources for hosting BTCPayServer easily
MIT License
584 stars 358 forks source link

help needed: using btcpay's nginx reverse proxy to redirect requests to another port #341

Closed ParmuSingh closed 4 years ago

ParmuSingh commented 4 years ago

I'm sorry devs to bother you with a git issue but I cannot seem to get answer anywhere else.

For more context: https://stackoverflow.com/questions/63123652/is-there-a-way-to-set-port-in-a-dns-forward and https://bitcoin.stackexchange.com/questions/97249/using-btcpay-server-along-with-a-web-server-in-a-single-machine

I have setup an aws ec2 instance and installed BTCPay Server docker version on it. I have set my domain as btcpay.example.com and all other environment variables are default and everything is working fine.

Except I want to run a web server on the same machine at example.com. As BTCPay server is already taking up port 80 and 443 it seems I have to run my webserver on another port. Let's say I choose port 6969.

After some help I have learnt than I need to use a nginx reverse proxy and redirect requests based on hostname. But how do I do that? I learnt BTCPay Server runs a nginx proxy on it own so I can make use of it.

So here is my questions: How can I use BTCPay Server's (docker version) inbuilt nginx reverse proxy to direct btcpay.example.com to btcpay server and example.com to my own (expressjs) web server?

As for DNS, I have only one A record of btcpay.example.com pointing to ec2 instance's ip.

NicolasDorier commented 4 years ago

Can you dockerize your web server? If so, just add a custom docker fragment (this is documented how).

Then use the following environment variable (btcpayserver-nginx.yml do that):

Then nginx will automatically configure lets encrypt and route myawesomeservice.com request to your own container.

If you can't dockerize your web server, I don't have any simple way for you.

https://www.youtube.com/watch?v=Up0dvorzSNM

Explains the architecture.

ParmuSingh commented 4 years ago

some update.

I tried what you said but I wasn't able to dockerise my web server. So this is what I did, I wrote a reverse proxy in express js that routes '/' requests to my normal web server (non-docker) and '/btcpay'requests to btcpay's nginx server (docker).

My reverse proxy being:

const proxy = require('express-http-proxy');
const app = require('express')();
const express = require('express')
const request = require('request');

app.use('/btcpay', proxy('http://localhost:10002')); // btcpay web server
app.use('/', proxy('http://localhost:10000')); // normal web server

app.listen(80, () => {
  request('http://localhost:10002', function (err, res, body) {
    if(err === null){
        console.log('btcpay web server is reachable from proxy server')
    }
    else{
        console.log('btcpay web server is not reachable from proxy server')
    }
  });
  request('http://localhost:10000', function (err, res, body) {
   if(err === null){
        console.log('normal web server is reachable from proxy server')
   }
   else{
    console.log('normal web server is not reachable from proxy server')
   }
  });
});

only http for now but before I implement SSL I've run into another problem.

example.com does direct me to my normal webserver but when I try example.com/btcpay/ I get 503 Service Temporarily Unavailable. I did some digging and tried doing this: https://docs.btcpayserver.org/FAQ/FAQ-Deployment/#cause-1-trying-to-access-my-btcpay-by-ip-address

Though it didn't help and I still see 503 error when accessing example.com/btcpay.

The Environment Variables used when installing were these:

export BTCPAY_HOST="example.com"
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-save-storage-s"
export BTCPAYGEN_REVERSEPROXY="nginx"
export REVERSEPROXY_HTTP_PORT="10002"
export REVERSEPROXY_HTTPS_PORT="10003"
export BTCPAYGEN_LIGHTNING="clightning"
export BTCPAY_ENABLE_SSH=true

Help?

NicolasDorier commented 4 years ago

Hi, the way you did should work. Did you try to see the logs of Nginx and btcpayserver by using docker logs ?

NicolasDorier commented 4 years ago

Have you tried REVERSEPROXY_DEFAULT_HOST="$BTCPAY_HOST" ?

ParmuSingh commented 4 years ago

i had tried REVERSEPROXY_DEFAULT_HOST="$BTCPAY_HOST" but I have made progress.

I am using my own express proxy (using https://github.com/http-party/node-http-proxy ) and running btcpay server with nginx proxy on port 10002 and 10003.

These are my final environment variables:

export BTCPAY_HOST="example.com"
export BTCPAY_ROOTPATH="/btcpay" // i think this is what I was missing before
export NBITCOIN_NETWORK="mainnet"
export BTCPAYGEN_CRYPTO1="btc"
export LIGHTNING_ALIAS="lnsolve"
export BTCPAYGEN_REVERSEPROXY="nginx"
export REVERSEPROXY_HTTP_PORT="10002"
export REVERSEPROXY_HTTPS_PORT="10003"
export REVERSEPROXY_DEFAULT_HOST="$BTCPAY_HOST"
export BTCPAYGEN_LIGHTNING="clightning"
export BTCPAY_ENABLE_SSH=true
export BTCPAYGEN_ADDITIONAL_FRAGMENTS="opt-txindex;opt-add-configurator;opt-add-librepatron"

other irrelevant change is that I'm not pruning and added some plugins I wanted to try.

with all set with including my reverse proxy as:

var express  = require('express');
var app      = express();
var httpProxy = require('http-proxy');
var webserver = 'http://localhost:10000',
    btcpayserver = 'http://localhost:10002/btcpay'

var apiProxy = httpProxy.createProxyServer();

PORT = 80

app.all("/btcpay/*", function(req, res) {
    console.log('redirecting to btcpay server');
    apiProxy.web(req, res, {target: btcpayserver});
});

console.log("Reverse proxy listening on port "+PORT)
app.listen(PORT);

Now if go to http://example.com/btcpay I get 404-Page not found with your beautiful face. image

but if go to http://<direct-ip-to-btcpay>:10002/btcpay it does work! This method skips the reverse proxy and I have ports open just in case to test. It's still http so I cannot login.

Now I believe the problem is with the reverse proxy I built. If there's anything I can improve do let me know.

ParmuSingh commented 4 years ago

above solution + my own nginx proxy works. SSL works.

NicolasDorier commented 4 years ago

If possible, do not use /btcpay there might be some side effect. (maybe not) The best is to have domain based routing rather than path based routing.

ParmuSingh commented 4 years ago

Yes. You're correct. I changed to subdomain level.