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
🔗 Recommended Related Technical Guides:
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 = Truein production, as error tracebacks reveal database schemas and secret API keys to visitors. - 🔒 Configure ALLOWED_HOSTS: Restrict
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']insettings.pyto prevent HTTP Host header poisoning. - 🔒 Enforce Secure Cookies: Enable
CSRF_COOKIE_SECURE = TrueandSESSION_COOKIE_SECURE = Trueto ensure cookies are only transmitted over encrypted HTTPS connections. - 🔒 Use Environment Variables for SECRETS: Store database passwords and
SECRET_KEYinside a local.envfile managed viapython-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.
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.

