How to Deploy a Flask Application with Gunicorn, Nginx, and SSL

Deploying a Flask application on a production server requires setting up Gunicorn as the application server, Nginx as the reverse proxy…

How to Deploy a Flask Application with Gunicorn, Nginx, and SSL
Photo by Ilya Pavlov on Unsplash

Deploying a Flask application on a production server requires setting up Gunicorn as the application server, Nginx as the reverse proxy, and implementing SSL for secure HTTPS connections. This guide walks you through the step-by-step process of deploying a Flask application using these tools, including configuration for HTTPS redirection and SSL setup with Certbot.

Overview of Tools

  • Flask: A lightweight web framework for Python.
  • Gunicorn: A Python WSGI HTTP server that handles client requests for the Flask app.
  • Nginx: A powerful HTTP server and reverse proxy to serve as the public-facing web server.
  • Certbot: A tool to obtain free SSL certificates from Let’s Encrypt, ensuring secure connections.

Step 1: Create and Configure the Flask Application

  1. Set Up the Flask App: Start by creating a project directory and setting up a virtual environment:
mkdir ~/myapp 
cd ~/myapp 
python3 -m venv venv 
source venv/bin/activate 
pip install flask gunicorn

2. Create a Sample Flask App: Create a file named app.py with a simple route:

from flask import Flask 
app = Flask(__name__) 
 
@app.route('/') 
def hello(): 
    return "Hello, Flask with Gunicorn and Nginx!" 
 
if __name__ == "__main__": 
    app.run()

3. Test Locally: Run the app locally to make sure it works:

python app.py

Navigate to http://127.0.0.1:5000 to confirm the app is running correctly.

Step 2: Set Up Gunicorn as the Application Server

  1. Run the App with Gunicorn: Use Gunicorn to serve the app on a specific port:
gunicorn -w 3 -b 127.0.0.1:8000 app:app

Test by visiting http://127.0.0.1:8000.

2. Set Up Gunicorn as a Systemd Service: To ensure the app starts on reboot, create a Systemd service for Gunicorn:

sudo nano /etc/systemd/system/myapp.service

Add the following configuration to this file:

[Unit] 
Description=Gunicorn instance to serve myapp 
After=network.target 
 
[Service] 
User=youruser 
Group=www-data 
WorkingDirectory=/home/youruser/myapp 
Environment="PATH=/home/youruser/myapp/venv/bin" 
ExecStart=/home/youruser/myapp/venv/bin/gunicorn -w 3 -b 127.0.0.1:8000 app:app 
 
[Install] 
WantedBy=multi-user.target
  • User: Replace youruser with your actual server username.
  • WorkingDirectory and Environment: Point to the project directory and virtual environment.

Enable and start the service:

sudo systemctl start myapp 
sudo systemctl enable myapp

Step 3: Install and Configure Nginx

  1. Install Nginx:
sudo apt update 
sudo apt install nginx

2. Set Up Nginx Configuration for Your Flask App: Create a new Nginx configuration file:

sudo nano /etc/nginx/sites-available/myapp

Add the following content to configure Nginx as a reverse proxy and enforce HTTPS:

server { 
    listen 80; 
    server_name yourdomain.com www.yourdomain.com; 
 
    # Redirect HTTP to HTTPS 
    return 301 https://yourdomain.com$request_uri; 
} 
 
server { 
    listen 443 ssl; 
    server_name yourdomain.com www.yourdomain.com; 
 
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; 
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; 
    include /etc/letsencrypt/options-ssl-nginx.conf; 
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
 
    location / { 
        proxy_pass http://127.0.0.1:8000; 
        proxy_set_header Host $host; 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header X-Forwarded-Proto $scheme; 
    } 
}
  • Replace yourdomain.com: Use your actual domain name.
  • The first server block handles HTTP traffic and redirects it to HTTPS.
  • The second server block configures HTTPS with SSL certificates and proxies requests to Gunicorn.

3. Enable the Configuration: Link this configuration to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled

Test and reload Nginx:

sudo nginx -t 
sudo systemctl reload nginx

Step 4: Set Up SSL with Certbot

  1. Install Certbot (if not already installed):
sudo apt install certbot python3-certbot-nginx

2. Obtain and Configure SSL Certificate: Run Certbot to obtain the SSL certificate and automatically configure Nginx:

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

Certbot will modify the Nginx configuration to include SSL directives.

3. Verify Auto-Renewal: Certbot is set to automatically renew certificates. To check, use:

sudo certbot renew --dry-run

Step 5: Testing and Verification

  1. Test HTTPS Redirect: Visit http://yourdomain.com and confirm it redirects to https://yourdomain.com.
  2. Check for Secure Connection: Ensure your browser displays a secure connection (lock icon) for HTTPS.
  3. Check Logs for Errors: If any issues arise, check the logs for debugging:
sudo journalctl -u myapp 
sudo tail -f /var/log/nginx/error.log

Summary

This guide has provided a comprehensive setup to deploy a Flask application with:

  • Gunicorn: Efficiently handling client requests.
  • Nginx: Acting as a reverse proxy and serving secure connections.
  • Certbot: Providing SSL for secure HTTPS connections.
  • HTTP to HTTPS Redirect: Ensuring all traffic goes through a secure connection.

This configuration will make your Flask app production-ready with secure, reliable, and scalable infrastructure.