I am trying to run a Bokeh plot/code through Flask using the server_document() function from bokeh.embed. Everything works well when the url is accessible publicly, using the lines of code.
script = server_document( url="http://*public_ip_address*:5000/bokeh_tool" )
return render_template( "index.html", script=script )
However, I want to run the same application on AWS behind a firewall. Is there a way to have the Bokeh server accessible without a public IP address (i.e. change the url to localhost or some equivalent) but maintain the same interactivity?
I"m not sure I really understand your expectation. When you embed a Bokeh server app in a page, that loads a JS script that opens a direct websocket connection back to the Bokeh server. So, the Bokeh server has to be reachable in one way or another from the browser. Bokeh offers features to block connections except from explicitly allowed origins, so you can prevent anyone from embedding the app except from your domain. Additionally there are auth hooks that you can define to condition app loading on some auth flow (e.g. the browser currently has a logged-in user).
Thank you for your quick response Bryan! Everything you said so far makes sense - that Bokeh server needs to have a direct websocket in order to maintain all the interactivity. Maybe I need to ask my question a different way.
Let’s say I have a Bokeh application running on computer A (let’s say port 5000) and that access to computer A is only allowed through https://mydomain.com (port 443). I can use NGINX to redirect the url (https://mydomain.com) to the port for Bokeh (localhost:5000) with no issue and I can get the Bokeh plot to render and keep all the interactivity.
Now let’s say I add an intermediate redirect step, either Flask/Django, so that it can handle additional APIs/features/functions. In this scenario, I would like to redirect using NGINX https://mydomain.com (port 443) → Flask/Django intermediate (port 5001), which works. I then would like to re-direct Flask to Bokeh (port 5000).
As in the initial question, I had hoped that server_document will allow me to achieve that redirect (from localhost:5001 → localhost:5000), but from your response, it sounds like I also need to set the websocket somehow to access 5001, but also through port 443 in order to connect to Bokeh? A bit of a long shot and a tall ask, I know, but do you have any ideas on how to achieve this?
Thanks again for you response so far and any help you can give.
I guess I am not quite fully understanding the problem or the ask. However, I am far from an expert on these things, either. I guess I would say this:
- The bokeh server has to be running on its own dedicated port (that’s just how things work at OS level)
- You can proxy the bokeh sever through nginx to any other domain/port if you like (you just have to make sure to set up websocket proxying, described in the docs)
If you proxy Bokeh server through nginx, then the URL/port you would pass to
server_document is whatever you configured nginx to expose publicly, e.g.
https://mydomain.com:5000. You can pass that to
server_document anywhere, on a page that is viewed in front of the proxy. I guess I don’t know why you need any redirect for the Bokeh server part, since you know exactly what its address in front of the proxy is.
I am not 100%, but I think you could even use nginx URL re-writing to makes something like
https://mydomain.com:443/bkapp be forwarded to
<internal ip>:5000 so that everything in front of the proxy appears to be on the same port from the outside (even though it is not internally).
Did some changes based on your suggestions, and I was able to use a URL for the server_document() in my Flask script that was then redirected by NGINX back to the Bokeh server. There is still a few things I will have to test, but I wanted to let you know that your help was greatly appreciated.