How to deploy Flask app on Linux Ubuntu using Nginx and Gunicorn

abdullah

By Abdullah Hussnain at Discovering CS

Updated: February 20, 2024      Reading Time: 15 min

How to deploy Python Flask application on Linux Ubuntu using Nginx and Gunicorn

Introduction

Are you ready to deploy your Python Flask application with the power duo - Gunicorn and Nginx? In this step-by-step guide, we will explore the seamless integration of Gunicorn as the WSGI server and Nginx as the reverse proxy and static file server. Elevate your web application's performance and security with this easy deployment process.

Prerequisites

Before we start the deployment process, let's make sure you have the essentials:

  • A Linux server (we recommend the reliable Ubuntu 23.10 LTS)
  • A PC or Laptop to remotely control your Linux server
  • A domain name pointing to your server

Meet Gunicorn: Your WSGI Server:

What is Gunicorn?

Gunicorn, or Green Unicorn, is a Python WSGI HTTP server designed to handle web requests efficiently. It's a crucial component for deploying Flask applications, ensuring they run smoothly and easily handle concurrent requests.

How Gunicorn Enhances Your Flask App?

Gunicorn excels in managing multiple connections concurrently, making it an ideal choice to serve your Flask app. Its asynchronous worker model and simple configuration make it a powerful tool for optimizing your application's performance.

Nginx: Your Trusty Sidekick

What is Nginx?

Nginx, pronounced 'engine-x,' is a high-performance web server and reverse proxy server. It's renowned for its speed, scalability, and efficient handling of static content. In our deployment, Nginx acts as the gateway, managing incoming requests and distributing them to Gunicorn.

What role does Nginx play in a deployment setup?

Nginx serves as a gateway in a deployment setup, managing incoming requests and distributing them to Gunicorn. It goes beyond a typical web server, excelling at load balancing, SSL termination, and handling static assets, enhancing the robustness and security of the application.

Step 1: Connect to Your Linux Server

Now that we've met our deployment superheroes let's connect to your Linux server and commence the deployment journey. Buckle up; it's going to be an exciting ride!

  1. ssh your_username@your_server_ip  

Step 2: Install Packages (if required)

  1. sudo apt install nginx  
  2. sudo apt install python  
  3. sudo apt install python3-pip
  4. sudo apt install unzip

Step 3: Transferring your project from a local Windows machine to a remote Linux server

Here's a step-by-step guide:

  1. Prepare Your Project Folder:
    Compress your project folder into a zip file using any compression software like WinZip or Winrar. Ensure that all the necessary files and directories are included in the zip archive.

  2. Access Command Prompt:
    Open the Command Prompt on your local Windows machine. You can do this by searching for "cmd" in the Start menu.

  3. Navigate to Project Zip File:
    Use the `cd` command to navigate to the directory where your project zip file is located. For example:

    1. cd C:\Path\To\Your\Project
  4. Copy Zip File to Remote Server:
    Utilize the `scp` command to securely copy the zip file to your Linux remote server.
    The syntax is as follows:

    1. scp -P Source_File_Path Destination_Path  

    Replace the placeholders with your specific details. Here's an example:

    1. scp -P project_file.zip abdullah@214.72.44.19: 

    This command copies the zip file ("project_file.zip") to the specified user's home directory on the remote server with the IP address "214.72.44.19".

  5. Provide Authentication:
    Enter the password or provide the necessary authentication details when prompted. This ensures a secure transfer.

  6. Verify Successful Copy:
    Once the transfer is complete, you should see a confirmation message indicating that the file has been copied successfully.

  7. Unzip the Copied Project:
    Once the file is transferred, remotely unzip the project using the `unzip` command on the server.

    1. unzip project_file.zip

Step 4: Prepare Your Flask App

Ensure your Flask app is ready for deployment. Install necessary dependencies and activate the virtual environment.

  1. sudo pip install virtualenv  

Create virtual environment:

  1. cd /path/to/your/project_folder  
  2. virtualenv venv 

Activate virtual environment:

  1. source venv/bin/activate  

Install Dependencies:

  1. pip install flask  

Now lets Install Gunicorn:

  1. pip install gunicorn  

Deactivate virtual environment using the `deactivate` command: 

  1. deactivate  

My project folder structure so far:

  1. project_folder    
  2.          |____static  
  3.          |             |___style.css    
  4.          |____templates  
  5.          |                  |___index.html    
  6.          |____ app.py    
  7.          |____ venv   

In my case code of  project_folder/app.py

  1. from flask import Flask, render_template  
  2.   
  3. app = Flask(__name__)  
  4.  
  5. @app.route('/')  
  6. def index():  
  7.     return render_template('index.html')  
  8.   
  9. if __name__ == '__main__':  
  10.     app.run(debug=False,host='0.0.0.0')  

Note: In your case the flask application code can be anything you like.

Step 5: Create a Systemd Service for Gunicorn

Create a systemd service file to manage Gunicorn as a background service.
The syntax is as follows:

  1. sudo nano /etc/systemd/system/your_app_name.service  

Replace the placeholders with your specific details. Here's an example:

  1. sudo nano /etc/systemd/system/discoveringcs.service  

Paste the following content, adjusting the placeholders:
The syntax is as follows:

  1. [Unit]  
  2. Description=Gunicorn instance to serve your_app_name  
  3. After=network.target  
  4.   
  5. [Service]  
  6. WorkingDirectory=/path/to/your/app  
  7. Environment="PATH=/path/to/your/app/venv/bin"  
  8. ExecStart=/path/to/your/project/venv/bin/gunicorn -w 4 --bind unix:/path/to/your/project/app.sock app:app 
  9.   
  10. [Install]  
  11. WantedBy=multi-user.target  

This version uses a Unix socket (`--bind unix:/path/to/your/app/app.sock`) instead of a network address. Ensure to replace the placeholders with your actual information.

  1. [Unit]  
  2. Description=Gunicorn instance to serve discoveringcs  
  3. After=network.target  
  4.   
  5. [Service]  
  6. WorkingDirectory=/home/abdullah/project_folder  
  7. Environment="PATH=/home/abdullah/project_folder/venv/bin"  
  8. ExecStart=/home/abdullah/project_folder/venv/bin/gunicorn -w 4 --bind unix:/home/abdullah/project_folder/discoveringcs.sock app:app

  9. [Install]  
  10. WantedBy=multi-user.target  

After saving the systemd service file, you can follow the same steps to enable and start the service:
The syntax is as follows:

  1. sudo systemctl enable your_app_name  
  2. sudo systemctl start your_app_name  

Replace the placeholders with your specific details. Here's an example:

  1. sudo systemctl enable discoveringcs  
  2. sudo systemctl start discoveringcs  

Step 6: Setup Firewall

  1. sudo ufw enable  
  2. sudo ufw status  
  3. sudo ufw allow ssh  
  4. sudo ufw allow http  
  5. sudo ufw allow https  

Step 7: Configure Nginx

Create an Nginx server block configuration file.
The syntax is as follows:
  1. sudo nano /etc/nginx/sites-available/your_app_name  

Replace the placeholders with your specific details. Here's an example:

  1. sudo nano /etc/nginx/sites-available/discoveringcs  

Insert the following configuration, adjusting the placeholders:
The syntax is as follows:

  1. server {  
  2.     listen 80;  
  3.     server_name your_domain_or_ip;  
  4.   
  5.     location / {  
  6.         include proxy_params;  
  7.         proxy_pass http://unix:/path/to/your/project/app.sock;  
  8.     }  
  9.     location /static {  
  10.         alias /path/to/your/app/static;  
  11.     }  
  12.     
  13. }  

Replace the placeholders with your specific details. Here's an example:

  1. server {    
  2.     listen 80;    
  3.     server_name discoveringcs.com www.discoveringcs.com;    
  4.     
  5.     location / {    
  6.         include proxy_params;    
  7.         proxy_pass http://unix:/home/abdullah/project_folder/discoveringcs.sock;    
  8.     }    
  9.     location /static {    
  10.         alias /home/abdullah/project_folder/static;    
  11.     }    
  12.       
  13. }   

Make sure to replace placeholders like `your_domain_or_ip` and `/path/to/your/project/` and `/path/to/your/app/` with your actual information.

Then create a symbolic link to this configuration file in the `sites-enabled` directory:

The command syntax is as follows:

  1. sudo ln -s /etc/nginx/sites-available/your_app_name /etc/nginx/sites-enabled  

Replace the placeholders with your specific details. Here's an example command:

  1. sudo ln -s /etc/nginx/sites-available/discoveringcs /etc/nginx/sites-enabled  
Remove the default Nginx server block if it exists.
  1. sudo rm /etc/nginx/sites-enabled/default  

Afterward, test the Nginx configuration and restart Nginx

  1. sudo nginx -t  
  2. sudo systemctl restart nginx  

Step 8: Point Your Domain

  1. Login to Your Domain Provider's Website:

    • Go to the website of your domain provider.
    • Log in with your account credentials.
  2. Navigate to DNS Management or Manage DNS:

    • Look for a section named "DNS Management," "Manage DNS," or similar. This is where you can configure your domain's DNS settings.
  3. Add the following Records:

    How to point domain 

Step 9: Secure Your Deployment with Let's Encrypt (Optional)

Ensure your deployment is secure by obtaining an SSL certificate with Let's Encrypt.

The command syntax is as follows:

  1. sudo apt install certbot python3-certbot-nginx -y  
  2. sudo certbot --nginx -d your_domain  
Replace the placeholders with your specific details. Here's an example command:
  1. sudo apt install certbot python3-certbot-nginx -y  
  2. sudo certbot --nginx -d discoveringcs.com www.discoveringcs.com  

Step 10: Celebrate Your Success!

Congratulations! Your Python Flask app is now live, powered by Gunicorn and Nginx. Access it through discoveringcs.com, and revel in the successful deployment.

Feel free to revisit this guide whenever you need to update or expand your application. Happy coding and deploying!

Comments by Readers:

Abu Huzaifa

This blog is very helpful for me.