Trouble understanding bokeh server allow-websocket-origin

I’m hoping the group might be able to help me understand the bokeh serve abc.py --allow-websocket-origin command a bit better. Right now I have an application that works, but only because I’m exposing port 5006 to the world. I don’t want to do that.

This is running on an AWS EC2, and I want to make it “production-worthy”. I’m running the Django and Bokeh server on the same machine.

I’m launching the following via supervisor so that it’s auto-launched at boot-up:

> bokeh serve bokeh_server_viz1 bokeh_server_viz2.py --allow-websocket-origin="*"

I use gunicorn/wsgi/nginx to launch my Django Application (for purposes of this question, could be a flask app)

Inside my view it looks like this:

def dynamic(request):

bokeh_server_url = “http://34.214.131.126:5006

app1_path = “/bokeh_server_viz1”

app2_path = “/bokeh_server_viz2”

session_server1 = pull_session(url=bokeh_server_url, app_path=app1_path)

server1_script = autoload_server(None, app_path=app1_path, session_id=session_server1.id, url=bokeh_server_url)

session_server2 = pull_session(url=bokeh_server_url, app_path=app2_path)

server2_script = autoload_server(None, app_path=app2_path, session_id=session_server2.id, url=bokeh_server_url)

context = {“server1_script”: server1_script,

“server2_script”: server2_script,

}

return render(request, ‘dashboard/dynamicviz.html’, context)

And all of these links work:

http://34.214.131.126/dynamicviz/

http://34.214.131.126:5006/

http://34.214.131.126:5006/bokeh_server_viz1

But my intent is for ONLY the Django server to see port 5006, but the firewall to block access to 5006 outside of the virtual machine.

FYI – feel free to navigate to the links above, but I’m changing them constantly.

So, my question – what combination of bokeh serve syntax and possibly nginx config do I need to block 5006 to the outside world, but allow the Django server to see the bokeh server running on the same machine? Is it even possible, or do I need to reconsider my approach?

Things I’ve tried that don’t work:

views.py (2.04 KB)

gunicorn.service (350 Bytes)

mysite (332 Bytes)

bokeh_serve.conf (267 Bytes)

···

bokeh serve abc.py --allow-websocket-origin=localhost:5006

bokeh serve abc.py --allow-websocket-origin=127.0.0.1:5006

bokeh serve abc.py --allow-websocket-origin=34.214.131.126


Attached files:

bokeh_serve.conf – runs at bootup via supervisor

gunicorn.service – runs at startup via systemctl

mysite – nginx configuration file located at /etc/nginx/sites-available

For what it’s worth, once I get this running I’m going to clean it up and post it to a public repository allow with directions as an example of of a Django application hosting static and dynamic Bokeh visualizations.

Thanks for the post. I’m struggling to expose my own bokeh application on an ec2 instance. I would love to see your eventual solution.

···

On Monday, September 18, 2017 at 1:20:24 PM UTC-4, Jonathan Bennett wrote:

I’m hoping the group might be able to help me understand the bokeh serve abc.py --allow-websocket-origin command a bit better. Right now I have an application that works, but only because I’m exposing port 5006 to the world. I don’t want to do that.

This is running on an AWS EC2, and I want to make it “production-worthy”. I’m running the Django and Bokeh server on the same machine.

I’m launching the following via supervisor so that it’s auto-launched at boot-up:

> bokeh serve bokeh_server_viz1 bokeh_server_viz2.py --allow-websocket-origin="*"

I use gunicorn/wsgi/nginx to launch my Django Application (for purposes of this question, could be a flask app)

Inside my view it looks like this:

def dynamic(request):

bokeh_server_url = “http://34.214.131.126:5006

app1_path = “/bokeh_server_viz1”

app2_path = “/bokeh_server_viz2”

session_server1 = pull_session(url=bokeh_server_url, app_path=app1_path)

server1_script = autoload_server(None, app_path=app1_path, session_id=session_server1.id, url=bokeh_server_url)

session_server2 = pull_session(url=bokeh_server_url, app_path=app2_path)

server2_script = autoload_server(None, app_path=app2_path, session_id=session_server2.id, url=bokeh_server_url)

context = {“server1_script”: server1_script,

“server2_script”: server2_script,

}

return render(request, ‘dashboard/dynamicviz.html’, context)

And all of these links work:

http://34.214.131.126/dynamicviz/

http://34.214.131.126:5006/

http://34.214.131.126:5006/bokeh_server_viz1

But my intent is for ONLY the Django server to see port 5006, but the firewall to block access to 5006 outside of the virtual machine.

FYI – feel free to navigate to the links above, but I’m changing them constantly.

So, my question – what combination of bokeh serve syntax and possibly nginx config do I need to block 5006 to the outside world, but allow the Django server to see the bokeh server running on the same machine? Is it even possible, or do I need to reconsider my approach?

Things I’ve tried that don’t work:

bokeh serve abc.py --allow-websocket-origin=localhost:5006

bokeh serve abc.py --allow-websocket-origin=127.0.0.1:5006

bokeh serve abc.py --allow-websocket-origin=34.214.131.126


Attached files:

bokeh_serve.conf – runs at bootup via supervisor

gunicorn.service – runs at startup via systemctl

mysite – nginx configuration file located at /etc/nginx/sites-available

For what it’s worth, once I get this running I’m going to clean it up and post it to a public repository allow with directions as an example of of a Django application hosting static and dynamic Bokeh visualizations.

Hi Jonathan,

When you navigate in your browser to "https://foo.com/bokeh_app" the HTTP request contains this information. In particular, the address you (or a user) has to type into the nav bar, i.e. "foo.com", is recorded as the ORIGIN.

This request makes its way to a Bokeh server, either directly, or though a proxy nginx, or whether embedding with server_doc, etc. If websockets adhered to the same cross-origin policies as HTTP then this would probably be the end of the story, we could just set a policy to disallow cross origin connections. But they don't, so Bokeh itself has to decide "should I permit this websocket connection?" By default, Bokeh is very conservative in this regard, basically it only allows connections with "localhost" as their origin. So if you want to connect to a Bokeh server from some other address, you have to tell Bokeh what the address will be, so it can decide to allow web socket connections to happen.

That is what --allow-websocket-origin is for.

When you specify "--allow-websocket-origin=foo.com" you are telling Bokeh: accept connections that report "foo.com" as their origin. So, TLDR: you want --allow-websocket-origin to reflect whatever public URL users will navigate to to reach your app. If users are connecting directly to the bokeh server, then it's whatever ip/dns name points at the bokeh server. If the server is behind a proxy, then it should be whatever ip/dns is pointing at the proxy.

So that's one half of your question. The other half, how to "hide" the server behind the proxy, s one I am less equipped to answer. But I an say a few words:

* The proxy needs to be set up to forward websocket connections, as well as origin headers
* If you want HTTPS, it needs some additional config for that
* Both of those are described in the user's guide with sample configs
* You need to configure your network so that only the proxy can see the Bokeh server

The last bit is what I can't help much with in detail. It depends entirely on your network configuration (i.e. are proxy and bk server on same machine or not?) as well as whatever firewall software you are using, etc.

Thanks,

Bryan

···

On Sep 18, 2017, at 13:20, Jonathan Bennett <[email protected]> wrote:

I'm hoping the group might be able to help me understand the bokeh serve abc.py --allow-websocket-origin command a bit better. Right now I have an application that works, but only because I'm exposing port 5006 to the world. I don't want to do that.

This is running on an AWS EC2, and I want to make it "production-worthy". I'm running the Django and Bokeh server on the same machine.
I'm launching the following via supervisor so that it's auto-launched at boot-up:

> bokeh serve bokeh_server_viz1 bokeh_server_viz2.py --allow-websocket-origin="*"

I use gunicorn/wsgi/nginx to launch my Django Application (for purposes of this question, could be a flask app)
Inside my view it looks like this:

def dynamic(request):
    bokeh_server_url = "http://34.214.131.126:5006"
    app1_path = "/bokeh_server_viz1"
    app2_path = "/bokeh_server_viz2"

    session_server1 = pull_session(url=bokeh_server_url, app_path=app1_path)
    server1_script = autoload_server(None, app_path=app1_path, session_id=session_server1.id, url=bokeh_server_url)

    session_server2 = pull_session(url=bokeh_server_url, app_path=app2_path)
    server2_script = autoload_server(None, app_path=app2_path, session_id=session_server2.id, url=bokeh_server_url)

    context = {"server1_script": server1_script,
               "server2_script": server2_script,
               }
    return render(request, 'dashboard/dynamicviz.html', context)

And all of these links work:

http://34.214.131.126/dynamicviz/
http://34.214.131.126:5006/
http://34.214.131.126:5006/bokeh_server_viz1

But my intent is for ONLY the Django server to see port 5006, but the firewall to block access to 5006 outside of the virtual machine.

FYI -- feel free to navigate to the links above, but I'm changing them constantly.

So, my question -- what combination of bokeh serve syntax and possibly nginx config do I need to block 5006 to the outside world, but allow the Django server to see the bokeh server running on the same machine? Is it even possible, or do I need to reconsider my approach?

Things I've tried that don't work:
> bokeh serve abc.py --allow-websocket-origin=localhost:5006
> bokeh serve abc.py --allow-websocket-origin=127.0.0.1:5006
> bokeh serve abc.py --allow-websocket-origin=34.214.131.126

------------

Attached files:
bokeh_serve.conf -- runs at bootup via supervisor
gunicorn.service -- runs at startup via systemctl
mysite -- nginx configuration file located at /etc/nginx/sites-available

For what it's worth, once I get this running I'm going to clean it up and post it to a public repository allow with directions as an example of of a Django application hosting static and dynamic Bokeh visualizations.

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/ee5d500d-5c33-4ea8-ae93-ec6f1e4b4d8d%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.
<views.py><gunicorn.service><mysite><bokeh_serve.conf>

1 Like