ansh.gandhi
ansh.gandhi

Reputation: 82

Hosting Bokeh Server with Tornado on AWS

When hosting Bokeh Server with Tornado on AWS, what could be a possible way to hide the Bokeh server from public IP access?

Upvotes: 1

Views: 1221

Answers (2)

Euan
Euan

Reputation: 579

I don't think you can avoid exposing the Bokeh server. Once the web browser has downloaded the <script> as generated by the autoload_server, it will then attempt to make a DIRECT connection to the Bokeh server instance based on the URL in the <script>. This connection then forms the WebSocket that is used for Bokeh interactivity.

For example:

# Start a Bokeh App for your interactive Graph
chart_app = Application(FunctionHandler(charts.chart_code))
server = Server({"/chart_app": chart_app}, address="localhost" port=5006, allow_websocket_origin=["localhost:80"])

# Handle a call to /chart
@app.route('/chart', methods=['GET'])
def chart_func():
    script = autoload_server(model=None, url='http://localhost:5006/chart_app')
    return render_template("embed_bootstrap.html", script=script)

The render_template will generate a full HTML web page, with a <div> added for the Bokeh chart:

<script
    src="http://localhost:5006/chart_app/autoload.js?bokeh-autoload-element=5eaa53a8-3336-40b1-8d29-f48457410a18&bokeh-app-path=/chart_app&bokeh-absolute-url=http://localhost:5006/chart_app"
    id="5eaa53a8-3336-40b1-8d29-f48457410a18"
    data-bokeh-model-id=""
    data-bokeh-doc-id=""
></script>
    </div>
</div>

Your browser will now try to connect directly to the Bokeh Server to retrieve the body of the <script>, and will then execute the js in the script. This will UPGRADE your HTTP connection to a WEBSOCKET and will communicate directly with the internal Bokeh server to provide the interactivity.

Unfortunately, this will fail as a hosted web server will not expose the Bokeh server on localhost:5006

What we need is a way to specify two host/port setting for the Bokeh server, one that it uses to create the actual internal Bokeh server (Normally on localhost:5006), and another to use to advertise the connection as the actual real host address and port in its <script> and also in the <script> code that is retrieved - that way we can let our own hosted HTTP server redirect these calls internally and the Browser only ever talks directly to the one server.

Upvotes: 0

Dave Maple
Dave Maple

Reputation: 8412

OPTION 1: Run Bokeh in a private subnet and Tornado in a public subnet.

You can place your Bokeh Server in a VPC private subnet, see: http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html This would ensure it gets a private IP address but would not be publicly accessible. If your Bokeh Server needs WAN egress you can place a NAT instance in a public subnet and route external traffic to the NAT from your private subnet.

Tornado would be placed in a public subnet making it publicly accessible and giving it access to Bokeh via the private network.

OPTION 2: Run Bokeh and Tornado on the same instance in a private subnet.

Place a Load Balancer in a public subnet and use the load balancer to expose Tornado but not Bokeh. This would make a lot of sense if you were using 2 or more AZs for fault tolerance but it would also achieve your goal in a single AZ.

OPTION 3: Run Bokeh and Tornado on the same instance in a public subnet.

Use an ec2 security group to allow Inbound access to Tornado ports but not to Bokeh ports. You would still be able to access Bokeh locally using the loopback address (localhost: 127.0.0.1).

Upvotes: 1

Related Questions