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.