DEV Community

Cover image for How to run a Flask App Over HTTPS, using Waitress and NGINX.  Updated for 2022.
Fabian Anguiano
Fabian Anguiano

Posted on • Updated on

How to run a Flask App Over HTTPS, using Waitress and NGINX. Updated for 2022.

Running a Flask app over HTTPS seems like it should be a simple exercise, however, there are not many up-to-date guides covering this topic. Here are the steps I took to run a Flask app over HTTPS.

Here are the basic steps.

  1. Set up a Flask App.
  2. Run it with Waitress.
  3. Use a reverse proxy with NGINX.
  4. Set up an SSL (updated).
  5. Configure the NGINX server rules.

This guide assumes you already have a Flask app up and running. If you don't here is a simple Flask App.

from flask import Flask


app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'> A very simple flask server !</h1>"

if __name__ == "__main__":
    #app.run(host='0.0.0.0')

Enter fullscreen mode Exit fullscreen mode

Running this should give you the following.

Alt Text

Okay, we have our Flask app running, why not just use this server? Per Flask documentation:

'While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well. Some of the options available for properly running Flask in production are documented here.'

One of the most simple solutions to this is to use Waitress Feel free to read the official guide on your own. But for this example we only need to make some minor changes. First install Waitress.

$ pip install waitress
Enter fullscreen mode Exit fullscreen mode

Next, we need to make some changes to our Flask app to let it know we are using Waitress.


from flask import Flask
#we import waitress here. 
from waitress import serve


app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'> A very simple flask server !</h1>"

if __name__ == "__main__":
    #app.run(host='0.0.0.0')
    #We now use this syntax to server our app. 
    serve(app, host='0.0.0.0', port=5000)

Enter fullscreen mode Exit fullscreen mode

Now we have our Flask app running with a production-ready server. But we still need our SSL. If you don't have one already, you can use Certbot or use a self-signed Cert.

(Updated: Thanks to Ömer Faruk Sancak)

Run these commands to get SSL or skip and do your own process.


sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx


sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

letsencrypt certonly -a webroot --webroot-path=/var/www/yourdomain.com/html/ -d yourdomain.com -d www.yourdomain.com


Enter fullscreen mode Exit fullscreen mode

We will make one final change to our Flask app. We need to let waitress know we will be using https. Documentation. We add url_scheme='https' to our app.

from flask import Flask
from waitress import serve


app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'> A very simple flask server !</h1>"

if __name__ == "__main__":
    #app.run(host='0.0.0.0')
    serve(app, host='0.0.0.0', port=5000, url_scheme='https')
Enter fullscreen mode Exit fullscreen mode

Now we have our SSL and are ready to use NGINX. If you don't already have it installed here is how to set it up.

Our Web Server rules will be at

etc/nginx/sites-available/default
Enter fullscreen mode Exit fullscreen mode

CD there and delete the example.

These will be our rules. Note

example.com & your.ip

This is just an example use your own domain/server address

server {
    listen 443 ssl;


    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;






    server_name example.com;



 location / {

            proxy_pass http://your.ip.adress:5000;
            proxy_set_header X-Real-IP $remote_addr;


        }


}



server {
    listen 80;

    server_name example.com;

    return 302 https://$server_name$request_uri;
}



Enter fullscreen mode Exit fullscreen mode

Note on this line.

proxy_pass http://your.ip.adress:5000;

If you are running your app on a different port you need to make sure these match. For example, if you are using port 3000 it would be

proxy_pass http://your.ip.adress:3000;

Okay, all of the configurations are done. But we need to let NGINX know, so we restart our server like so.

sudo systemctl status nginx

Refresh and you should see the new server running with the SSL.

Alt Text

Top comments (6)

Collapse
 
keyiflerolsun profile image
Ömer Faruk Sancak • Edited
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Enter fullscreen mode Exit fullscreen mode
letsencrypt certonly -a webroot --webroot-path=/var/www/yourdomain.com/html/ -d yourdomain.com -d www.yourdomain.com
Enter fullscreen mode Exit fullscreen mode
Collapse
 
thetrebelcc profile image
Fabian Anguiano

Added to the article, thanks!

Collapse
 
mcsage profile image
Stephan Hohn

Thanks, after a long search on the web I found your post which helped me to fix flask-oicd redirect behind ssl nginx proxy.
Using waitress with serve(app, host='0.0.0.0', port=5000, url_scheme='https') fixed the redirect which was always http instead of https.

Collapse
 
perplexedfox profile image
PerplexedFox

Now we have our SSL and are ready to use NGINX. If you don't already have it installed here is how to set it up.

Typo in the link (.fcom)

Collapse
 
ilya12077 profile image
ilya12077

thanks

Collapse
 
robomate profile image
Robomate