Nginx proxy pass

I am using bokeh v2.2.1, Nginx v 1.18.0 on Ubuntu 20.04

My bokeh app works fine when i give public_ip:5006. I am trying to have nginx listen on 443 and fwd to my bokeh app. Both bokeh and nginx are on the same VM.

I am invoking bokeh as

bokeh serve kw_Clustering_Comparison.py --allow-websocket-origin=* ( i am using * just to sort out this issue first)

my nginx conf is as follows:

server {
listen 443 ssl;
server_name www.mydomain.net;
ssl_certificate /etc/letsencrypt/live/mydomain.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.net/privkey.pem;

location / {
    proxy_pass http://127.0.0.1:5006;
}

}

I get a blank white page and no response. (But note the tab header showing ‘Bokeh app’)

And I see this on the terminal window where i served bokeh:

2020-10-13 16:58:37,057 400 GET /kw_Clustering_Comparison/ws (127.0.0.1) 0.53ms

Is there something I could change to fix this? I saw a couple of similar issues raised here but they are quite old (2014 or so) and most of that discussion went over my head :).

Any help in this regard is greatly appreciated!

PS, I initially tried serving this with nginx + gunicorn + flask + bokeh, but since i got this kind of an issue i tried with nginx + bokeh and i realize this issue is just between nginx and bokeh as the issue persists even now. If I type my.public.ip:5006 it works fine.

You have to alter your Nginx config quite a bit to make it work with WebSockets. Your current configuration is definitely not enough. A concrete examples of what the config should look like are pretty easy to find online.

1 Like

In particular there are sample configs in the docs:

https://docs.bokeh.org/en/latest/docs/user_guide/server.html#basic-reverse-proxy-setup

1 Like

Simply brilliant! This worked like a charm. You are a life saver, Bryan!

I was helped out on another issue a few weeks ago as well. As a token of appreciation for your support and generosity in helping out others, here is a small contribution from me.

1 Like

Thank you, p-himik

@Bryan, @p-himik

Hi there,

I have two Outstanding things for which i need some help:

Issue 1. Right now I am doing bokeh serve first, then have it served by flask app through gunicorn --bind 0.0.0.0:5000 wsgi:app. (app is my flask app pointing to my bokeh app with file name ‘env.py’.

I am able to host the bokeh app but only as direct mapping of domain to the port number. i.e. https://mydomain will show the app. Here is my config that works and shows my bokeh app for https://mydomain (but only if i directly proxy it to 5006):

location / {
    proxy_pass http://127.0.0.1:5006;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host:$server_port;
    proxy_buffering off;
}

When i try to proxy pass 'location /' to port 5000 served by gunicorn i get blank page. What should i change to make it work? Also, what is your recommended way of hosting bokeh apps through nginx? (should we use gunicorn/flask in between bokeh and nginx or directly link bokeh with nginx?)

Issue 2:
I need to host multiple other apps using same nginx server, so i need https://mydomain to show a landing page (not bokeh app) with images hyperlinked to other apps. The issue i am facing is to have location / for a landing page and location/app1/ (or something like that) for my bokeh app. When i try to use something like below config i get a blank page (for mydomain/env) with only browser tab having title ‘Bokeh Application’ (like i was getting earlier).

location / {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host:$server_port;
    proxy_buffering off;
}

location /env/ {
    rewrite ^/env/(.*)$ /$1 break;
    proxy_cache_bypass $http_upgrade
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $host:$server_port;
    proxy_buffering off;
    proxy_pass http://127.0.0.1:5006;
}

proxying to 5000 also didn’t work.
Basically, https://mydomain works but not https://mydomain/env.

Any help in this is appreciated! (apologies for long post, but i thought this info is needed to understand what i am trying to do)

I noticed something while configuring flask and it probably might tell where i am going wrong. I am running bokeh and flask on an Ubuntu vm and testing it thru browser from my laptop (win 10). When i configure flask app to point to the public.ip.of.vm:5006/env then it works (i.e. public.ip.of.vm:5000 on my laptop browser shows the bokeh app), but if i configure flask app to point to localhost:5006/env it shows blank page. What is the correct way to configure flask in this scenario?

from bokeh.resources import CDN

from flask import Flask, render_template
from bokeh.embed import server_document,server_session
from bokeh.client import pull_session

app = Flask(name)

@app.route("/")

def index():
#myurl = “http://public.ip.of.vm:5006/env
myurl = “https://localhost:5006/env
bokeh_script = server_document(myurl)
return render_template(“index.html”,bokeh_script=bokeh_script)

#run the app
if name == “main”:
app.run(host=‘0.0.0.0’) #app.run(debug=True)

I don’t know enough of Nginx to be able to answer without researching it. Either way, it seems to me like some Nginx support forum or StackOverflow would be a better place for this question because at this point Bokeh is pretty much out of the question.