Learn how to deploy Django on Ubuntu 24.04 using Gunicorn as the WSGI application server and Nginx as the reverse proxy. This setup is widely used in production environments because it is stable, efficient, and easy to maintain.
Introduction
Deploying a Django application to production requires a reliable web server, a stable application server, and a clean configuration that ensures performance and security.
Our goal is to create a deployment structure that is secure, scalable, and suitable for real-world applications.
Step 1 - Update the Server
We begin by ensuring the system packages are fully updated.
sudo apt update && sudo apt upgrade -y
Install essential development packages required for building Python dependencies.
sudo apt install python3 python3-venv python3-pip python3-dev build-essential -y
These packages allow Python modules with compiled extensions to install correctly.
Step 2 - Create a Project Directory
Production deployments should never run directly from a home directory.
We create a clean application directory.
sudo mkdir -p /var/www/django_app
Give ownership to the current user.
sudo chown -R $USER:$USER /var/www/django_app
Move inside the directory.
cd /var/www/django_app
Step 3 - Create Python Virtual Environment
A virtual environment isolates project dependencies and prevents conflicts with system packages.
Create the environment:
python3 -m venv venv
Activate it:
source venv/bin/activate
Upgrade pip:
pip install --upgrade pip
Step 4 - Install Django and Gunicorn
Install the core dependencies.
pip install django gunicorn
If the project uses additional dependencies, install them from the requirements file.
pip install -r requirements.txt
Step 5 - Create or Upload the Django Project
If starting fresh, create the project.
django-admin startproject project .
Run database migrations.
python manage.py migrate
Create an admin user.
python manage.py createsuperuser
This ensures static assets are served efficiently by Nginx rather than Django.
Step 6 - Configure Django for Production
Open the Django settings file.
nano project/settings.py
Update the ALLOWED_HOSTS setting.
ALLOWED_HOSTS = ["server_ip", "domain.com"]
Add static file configuration.
STATIC_ROOT = "/var/www/django_app/static"
Save and exit.
Collect static files.
python manage.py collectstatic
Step 7 - Install and Configure Nginx
Install Nginx.
sudo apt install nginx -y
Allow HTTP through the firewall.
sudo ufw allow 'Nginx Full'
Create a new site configuration.
sudo nano /etc/nginx/sites-available/django_app
Add the following configuration.
server {
listen 80;
server_name domain.com server_ip;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /var/www/django_app;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn/gunicorn.sock;
}
}
Enable the site.
sudo ln -s /etc/nginx/sites-available/django_app /etc/nginx/sites-enabled
Test configuration.
sudo nginx -t
Reload Nginx.
sudo systemctl restart nginx
Step 8 - Create Gunicorn Systemd Service
Gunicorn creates the socket file used by Nginx. Ensure proper permissions exist.
Create runtime directory.
sudo mkdir -p /run/gunicorn
Set permissions.
sudo chown www-data:www-data /run/gunicorn
Running Gunicorn manually is not suitable for production. We configure systemd so the application runs automatically.
Create the service file.
sudo nano /etc/systemd/system/gunicorn.service
Add the configuration below.
[Unit]
Description=Gunicorn daemon for Django
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/django_app
ExecStart=/var/www/django_app/venv/bin/gunicorn \
--workers 3 \
--bind unix:/run/gunicorn/gunicorn.sock \
project.wsgi:application
[Install]
WantedBy=multi-user.target
Save the file.
Reload systemd.
sudo systemctl daemon-reload
Start Gunicorn.
sudo systemctl start gunicorn
Enable it on boot.
sudo systemctl enable gunicorn
Verify status.
sudo systemctl status gunicorn
Step 9 - Configure Static File Serving
Nginx should handle static assets to improve performance.
Ensure static files exist.
python manage.py collectstatic
Nginx already serves /static/ from:
/var/www/django_app/static
This avoids unnecessary load on Gunicorn.
Step 10 - Secure the Application with HTTPS
Production deployments should always use SSL.
Install Certbot.
sudo apt install certbot python3-certbot-nginx -y
Generate the certificate.
sudo certbot --nginx -d domain.com
Certbot automatically updates the Nginx configuration and sets up automatic renewal.
Troubleshooting
If you get error in gunicorn service, try to run gunicorn manually in debug mode:
gunicorn project.wsgi:application --bind 0.0.0.0:8000 --workers 2 --log-level debug
Step 12 - Production Optimization
A stable deployment requires a few practical optimizations.
Increase Gunicorn workers
workers = (2 × CPU cores) + 1
Example:
--workers 5
Enable logging
Logs help diagnose production issues.
Gunicorn logs can be viewed with:
journalctl -u gunicorn
Nginx logs are located at:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
Restart services after updates
sudo systemctl restart gunicorn
sudo systemctl reload nginx
Final Thoughts
Deploying Django with Gunicorn and Nginx on Ubuntu 24.04 creates a production-ready environment capable of serving real applications reliably.
Gunicorn manages Python application execution, while Nginx efficiently handles HTTP requests, static files, and reverse proxy responsibilities. This architecture ensures stability, performance, and scalability.
By following this deployment approach, we build a clean and maintainable infrastructure that can support both small projects and large production workloads.

