Deploy a Flask Website on Nginx with uWSGI

Updated on November 21, 2023
Deploy a Flask Website on Nginx with uWSGI header image

Once you've created a Flask app, you'll find that the included web server is best suited for development. In this guide, you'll learn how to host your Flask app on a Debian 10 cloud server instance with an Nginx web server, Certbot for SSL, and uWSGI application server.

Prerequisites

  • A fully-updated Debian 10 server
  • Root privileges to the server
  • A registered domain name is optional, but recommended.

You can follow this tutorial without a domain name by using localhost in the Nginx configuration step. You won't be able to install a valid SSL certificate, so skip the Certbot instructions.

1. Install Nginx

  1. Install the Nginx package.

     # apt install nginx
  2. Test Nginx by navigating to the server's IP address in a browser. Verify the Nginx web page appears.

  3. If you have a registered domain, set up DNS entries for your server. This tutorial uses the following values:

    • IPv4 address: 192.0.2.123
    • Server names: example.com & www.example.com

2. Set up Flask and uWSGI

  1. Install uWSGI and Flask.

     # apt install python3-pip python-dev
     # pip3 install uwsgi flask
  2. Create a website home directory.

     # mkdir /var/www/example
  3. If you have a Flask application to deploy, move it to the /var/www/example directory.

    Or, you can create a simple Flask application for testing this guide.

     # nano /var/www/example/main.py

    Paste in:

     from flask import Flask
     app = Flask(__name__)
    
     @app.route("/")
     def index():
     return "Hello World!"
    
     if __name__ == "__main__":
     app.run(host="0.0.0.0")
  4. Create config-uwsgi.ini for uWSGI.

     # nano /var/www/example/config-uwsgi.ini

    Paste in:

     [uwsgi]
    
     app = main
     module = %(app)
     callable = app
    
     socket = /var/www/example/example.sock
     chdir = /var/www/example
     chmod-socket = 666
    
     processes = 4
     die-on-term = true

    The processes line can be set higher for larger servers.

3. Set up Nginx

  1. Remove the default Nginx configuration.

     # rm /etc/nginx/sites-enabled/default
  2. Create a new Nginx configuration file.

     # nano /var/www/example/config-nginx.conf

    Paste in the following content. If you do not have a registered domain name, use localhost for server_name in place of example.com and www.example.com.

     server {
    
         listen 80;
         listen [::]:80;
    
         server_name example.com www.example.com;
    
         location / {
             include uwsgi_params;
             uwsgi_pass unix:/var/www/example/example.sock;
         }
     }
  3. Create a symbolic link from your Nginx configuration to the conf.d directory.

     # ln -s /var/www/example/config-nginx.conf /etc/nginx/conf.d/
  4. Restart Nginx.

     # systemctl restart nginx

4. Run uWSGI

  1. Nginx is configured to proxy traffic to uWSGI, but the service isn't running yet. Start uWSGI with nohup.

     # nohup uwsgi /var/www/example/config-uwsgi.ini &
  2. Press Ctrl + C to send the SIGINT signal and see that the process still runs in the background. For production use, we recommend running uWSGI at startup under systemd.

  3. Navigate to your site in a web browser and verify you see the "Hello World!" message.

5. Install SSL Certificate

If you have a public domain name, configure the webserver for HTTPS with a free Let's Encrypt certificate using Certbot.

  1. Install Certbot.

     # apt install certbot python-certbot-nginx
  2. Request an SSL certificate.

     # certbot --nginx
  3. Answer the questions when prompted by Certbot and agree to the terms of service.

  4. Certbot will ask which domain names should have SSL support, press Enter to select all names.

  5. When prompted, choose to redirect HTTP traffic to HTTPS.

Conclusion

After following this beginner tutorial, your Nginx web server runs Flask application on uWSGI, secured with Certbot. For full production use, you should also run uWSGI on startup as a normal user with limited permissions. See the uWSGI best practices and Flask documentation for more information.