I love AWS and take full advantage of their Load Balancers (LB) to direct traffic to my web server instances. I also make use of the “free” SSL certs (through Certificate Manager) so all my sites/applications run under https which is a good practice.

An issue that always seems to rear its ugly head is the https to http redirect problem when a Flask app is deployed behind a load balancer or proxy.

The diagram below shows my typical (simplified) setup with one or more EC2 instances sitting behind a LB. The Docker container has a gunicorn http server to front the Flask application.

All traffic to the application(s) is sent over https to the load balancer. Based on header rules and target groups the LB figures out where to send the traffic and then does so using http (there is no need to use https behind the LB). The issue is that the flask app thinks it’s running as http so whenever it does a redirect the fully qualified url will be http and that’s clearly a problem.

We need to instruct the app to pay attention to X-Forwarded-Host and X-Forwarded-For that’s coming from the LB and thankfully there is a very simple fix explained here. As it states, Werkzeug ships with a fix to solve this problem. In my case I use the ProxyFix solution to keep everything simple.

In my create_app() factory method I check to see if we’re running in production and insert the ProxyFix instruction:

if 'production' == app.config['FLASK_ENV']:
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=2)

Note the num_proxies=2 setting. This is needed because we have 1) the load balancer and 2) the gunicorn server sitting in front of the app so it has two proxies.

That’s all there is to it.

Leave a comment