How to Deploy a Django/Flask Application with Gunicorn and Nginx

The standard production pattern for Python web applications is Gunicorn (a WSGI application server) running your Django or Flask app, with Nginx in front handling public traffic, static files, and SSL.

Prerequisites

  • Python installed (see How to Install Python on Ubuntu & Debian)
  • Nginx installed
  • A Django or Flask application ready to deploy

Step 1 — Transfer Your Application

rsync -avz ./myapp/ deploy@YOUR_SERVER_IP:/var/www/myapp/

Step 2 — Create a Virtual Environment

cd /var/www/myapp
python3 -m venv venv
source venv/bin/activate

Step 3 — Install Dependencies

pip install -r requirements.txt
pip install gunicorn

Step 4 — Test Gunicorn Directly

For Django:

gunicorn --bind 127.0.0.1:8000 myproject.wsgi

For Flask:

gunicorn --bind 127.0.0.1:8000 app:app

Confirm it works, then stop it (Ctrl+C) before proceeding to a proper service setup.

Step 5 — Create a systemd Service for Gunicorn

sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=Gunicorn instance for myapp
After=network.target

[Service]
User=deploy
Group=www-data
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
ExecStart=/var/www/myapp/venv/bin/gunicorn --workers 3 --bind unix:/var/www/myapp/myapp.sock myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Replace myproject.wsgi:application with app:app for Flask.

Step 6 — Start and Enable the Service

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp

Step 7 — Configure Nginx

sudo nano /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name myapp.example.com;

    location /static/ {
        alias /var/www/myapp/static/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/var/www/myapp/myapp.sock;
    }
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 8 — Collect Static Files (Django Only)

python manage.py collectstatic

Step 9 — Add HTTPS

sudo certbot --nginx -d myapp.example.com

Deploying Updates

cd /var/www/myapp
git pull
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
sudo systemctl restart myapp

Common Errors

502 Bad Gateway — check the Gunicorn service status and logs:

sudo systemctl status myapp
sudo journalctl -u myapp -n 50

Static files return 404 — confirm collectstatic was run (Django) and the Nginx alias path matches your actual static files location.

Permission denied on the socket file — verify the Nginx user (www-data) has access to the directory containing the socket.

Best Practices

  • Use a Unix socket rather than a TCP port between Gunicorn and Nginx for slightly better performance and simpler firewall rules
  • Set --workers based on available CPU cores (a common formula is 2 × cores + 1)
  • Never run Django with DEBUG = True in production

Continue Reading

Browse more articles in Programming Languages & Runtimes.

  • django deployment, flask deployment, gunicorn, python wsgi, nginx
  • 0 Пользователи нашли это полезным
Помог ли вам данный ответ?

Связанные статьи

How to Install PHP on Ubuntu & Debian (Complete Guide)

PHP powers a huge share of the web, including WordPress, Laravel, and Magento. This guide covers...

How to Install Node.js on Ubuntu & Debian (with NVM)

Node.js is a fast JavaScript runtime for building APIs, web applications, and backend services....

How to Install Python on Ubuntu & Debian

Python powers web frameworks like Django and Flask, automation scripts, and data applications....

How to Install Java (OpenJDK) on Ubuntu & Debian

Java powers enterprise applications, build tools like Maven and Gradle, and platforms like...

How to Install Composer for PHP Dependency Management

Composer is PHP's standard dependency manager, used by virtually every modern PHP framework...