Skip to main content

How to deploy Django on Ubuntu 24.04 (production guide)

TL;DR

Complete guide to deploying a production Django application on Ubuntu 24.04 with Gunicorn, nginx, PostgreSQL, and SSL.

Key facts

Topology
Django on Ubuntu 24.04

TL;DR

This guide covers deploying a production Django application on Ubuntu 24.04 with Python, Gunicorn, nginx, PostgreSQL, and SSL.

Prerequisites

  • Ubuntu 24.04 LTS with root or sudo access
  • A domain name pointing to your server
  • Your Django application in a Git repository

Step 1 — System preparation

sudo apt update && sudo apt upgrade -y
sudo apt install -y python3 python3-venv python3-pip git build-essential libpq-dev

Create a deploy user:

sudo adduser deploy
sudo usermod -aG sudo deploy

Step 2 — PostgreSQL

sudo apt install -y postgresql postgresql-contrib
sudo -u postgres createuser --interactive myappuser
sudo -u postgres createdb myappdb -O myappuser
sudo -u postgres psql -c "ALTER USER myappuser WITH PASSWORD 'secure-password-here';"

Step 3 — Deploy the application

sudo mkdir -p /var/www/myapp
sudo chown deploy:deploy /var/www/myapp
cd /var/www/myapp
git clone git@github.com:yourorg/myapp.git .
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

Run Django setup commands:

python manage.py migrate
python manage.py collectstatic --noinput
python manage.py createsuperuser

Step 4 — Gunicorn

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

[Unit]
Description=Gunicorn daemon for Django
After=network.target

[Service]
User=deploy
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/venv/bin/gunicorn myapp.wsgi:application \
    --workers 3 \
    --bind unix:/run/gunicorn.sock \
    --timeout 120 \
    --access-logfile /var/log/gunicorn/access.log \
    --error-logfile /var/log/gunicorn/error.log
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo mkdir -p /var/log/gunicorn
sudo chown deploy:www-data /var/log/gunicorn
sudo systemctl start gunicorn
sudo systemctl enable gunicorn

Step 5 — nginx

server {
    listen 80;
    server_name example.com;

    location /static/ {
        alias /var/www/myapp/staticfiles/;
        expires 30d;
    }

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

    location / {
        proxy_pass http://unix:/run/gunicorn.sock;
        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;
    }
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 6 — SSL and firewall

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

With Reflex

Install reflexd to monitor your Django stack end-to-end. Reflex tracks Gunicorn worker health, nginx error rates, database connectivity, disk usage, and SSL certificate expiry. It can deploy updates with zero downtime, run migrations safely, and auto-recover from common failures. See How it works.