Tutorials

How to Deploy Python Django / Flask App with Gunicorn and Nginx on Ubuntu

How to Deploy Python Django & Flask App with Gunicorn & Nginx - CpanelFree Guide
Written by Blog

Quick Answer: To deploy a Python Django or Flask web application on Ubuntu: 1) Create an isolated Python virtual environment (python3 -m venv myenv), 2) Install Gunicorn as the WSGI server, 3) Create a Systemd socket and service file to manage the Gunicorn daemon, and 4) Configure Nginx to serve static/media files directly and proxy dynamic requests to the Gunicorn UNIX socket.

Step 1: Set Up Python Virtual Environment & Gunicorn

sudo apt update && sudo apt install -y python3-pip python3-venv python3-dev libpq-dev nginx
cd /var/www/my-django-app
python3 -m venv myenv
source myenv/bin/activate
pip install -r requirements.txt gunicorn

Step 2: Create Systemd Service File for Gunicorn

Create /etc/systemd/system/gunicorn.service:

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/my-django-app
ExecStart=/var/www/my-django-app/myenv/bin/gunicorn           --access-logfile -           --workers 3           --bind unix:/run/gunicorn.sock           myproject.wsgi:application

[Install]
WantedBy=multi-user.target
# Start and enable Gunicorn service
sudo systemctl start gunicorn && sudo systemctl enable gunicorn

Step 3: Configure Nginx Reverse Proxy for Python

Create /etc/nginx/sites-available/django.conf:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    
    location /static/ {
        root /var/www/my-django-app;
    }

    location /media/ {
        root /var/www/my-django-app;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
sudo ln -s /etc/nginx/sites-available/django.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Managing Static Files with WhiteNoise in Production Django

While Nginx can serve static assets directly, installing WhiteNoise allows Django to serve compressed, cache-busting static files directly through WSGI with zero external configuration:

# In settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    # ...
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

Automating Django Migrations and Static Collection via Bash Script

#!/bin/bash
# deploy.sh
source myenv/bin/activate
git pull origin main
pip install -r requirements.txt
python manage.py migrate --noinput
python manage.py collectstatic --noinput
sudo systemctl restart gunicorn

Production Security Checklist for Django Deployments

  • 🔒 Set DEBUG = False: Never run DEBUG = True in production, as error tracebacks reveal database schemas and secret API keys to visitors.
  • 🔒 Configure ALLOWED_HOSTS: Restrict ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com'] in settings.py to prevent HTTP Host header poisoning.
  • 🔒 Enforce Secure Cookies: Enable CSRF_COOKIE_SECURE = True and SESSION_COOKIE_SECURE = True to ensure cookies are only transmitted over encrypted HTTPS connections.
  • 🔒 Use Environment Variables for SECRETS: Store database passwords and SECRET_KEY inside a local .env file managed via python-dotenv.

Why use UNIX sockets instead of TCP ports (127.0.0.1:8000) for Gunicorn?

UNIX domain sockets (unix:/run/gunicorn.sock) communicate directly through kernel memory buffers, bypassing the TCP network stack overhead and delivering up to 15% higher request throughput.

Deploy Python Apps with Ease on CpanelFree

Deploy Python applications, WSGI microservices, and databases with root control on CpanelFree cloud servers.

Explore Cloud Servers

Frequently Asked Questions

How many Gunicorn workers should I configure?

The standard formula recommended by the Gunicorn team is (2 x $num_cores) + 1. On a 2 vCPU VPS, configure 5 workers for optimal throughput.

Configuring Celery Background Task Workers with Redis on Ubuntu

For long-running tasks like sending notification emails or generating PDF reports in Django, run Celery with a Redis message broker alongside Gunicorn:

# Install Redis server and Celery
sudo apt install -y redis-server
pip install celery redis

# Launch Celery worker daemon
celery -A myproject worker --loglevel=info --concurrency=4

Pro Sysadmin Tip: Monitoring Gunicorn Socket Status

Verify UNIX socket communication health using sudo systemctl status gunicorn.socket and inspect real-time worker logs via sudo journalctl -u gunicorn -f.

Deploying Python Django and Flask applications with Gunicorn, Systemd, and Nginx ensures sub-second response times, robust security isolation, and effortless production scalability.

Configuring Automated PostgreSQL Database Backups for Django

Protect your production Django data by configuring a nightly cron job that exports compressed PostgreSQL database dumps directly to encrypted offsite cloud storage:

# Automated PostgreSQL Nightly Dump
0 3 * * * pg_dump -U djangouser djangodb | gzip > /var/backups/django_$(date +\%F).sql.gz

How do I run Django database migrations during production updates?

Activate your virtual environment and run python manage.py migrate --noinput followed by sudo systemctl restart gunicorn to apply schema updates without downtime.

Additionally, configuring Gunicorn with Systemd socket activation ensures that incoming web traffic automatically spawns application worker threads with zero manual intervention.

Following this production deployment architecture ensures your Django and Flask web applications operate with maximum security, reliability, and speed on Linux VPS servers.

Setting up dedicated virtual environments and automated Gunicorn process monitoring guarantees maximum stability and performance for your mission-critical Python web applications.

Following this production architecture ensures complete data isolation, high concurrency handling, and rapid response times for full-stack Python web development projects.

Employing modern WSGI process management combined with Nginx edge proxy caching unlocks blazing performance for production web frameworks on Ubuntu.

About the author

Blog

DevOps architect and Linux sysadmin specializing in server hardening, OpenLiteSpeed performance optimization, and free cloud hosting infrastructure.

Leave a Comment