Deploying a Django application in a production environment requires more than just running the development server. For a scalable, secure, and reliable setup, Gunicorn (a WSGI HTTP server) and Nginx (a high-performance reverse proxy server) are the preferred choices. In this guide, we’ll walk you through every step of hosting your Django project using Gunicorn and Nginx on a Linux server.
Why Use Gunicorn and Nginx?
Before diving into the setup, here’s why this combo is popular:
- Gunicorn efficiently runs your Django app by handling multiple requests concurrently.
- Nginx serves static files, manages SSL, and forwards requests to Gunicorn.
- Combined, they provide improved performance, security, and scalability.
Prerequisites
Before you begin, make sure you have:
- A Linux-based server (Ubuntu 20.04 or later recommended)
- Python 3.x installed
- A Django project ready
- Root or sudo access to the server
- A domain name (optional, but recommended)

Step 1: Install Required Packages
SSH into your server and update it:
sudo apt update && sudo apt
Step 2 – Install Nginx and required tools
Install Nginx using the command below:
sudo apt install python3-pip python3-dev nginx
Step 3 – Allow Nginx through the firewall
Allow Nginx through the firewall using the command below:
sudo ufw app list
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status # Verify Nginx HTTP/HTTPS access
Step 4 – Install & Configure PostgreSQL
Let’s install PostgreSQL using the command below:
While you are logged into the server, run following commands to install, start, enable and see the status of postgresql database:
sudo apt-get install postgresql postgresql-contrib
sudo systemctl start postgresql.service
sudo systemctl enable postgresql.service
sudo systemctl status postgresql.service
Step 5 -Postgres Database & User Setup
sudo -u postgres psql
You should now be logged into the pg shell
Create a database
CREATE DATABASE dydevops_db;
Create user
CREATE USER dbmwshop WITH PASSWORD 'MaWbc1$23!';
Set default encoding, tansaction isolation scheme (Recommended from Django)
ALTER ROLE dbmwshop SET client_encoding TO 'utf8';
ALTER ROLE dbmwshop SET default_transaction_isolation TO 'read committed';
ALTER ROLE dbmwshop SET timezone TO 'UTC';
Give User access to database
GRANT ALL PRIVILEGES ON DATABASE dydevops_db TO dbmwshop;
Quit out of Postgres
\q
Step 6 – Creating a python virtual environment
sudo pip3 install virtualen
This will install a virtual environment package in python. Let’s create a project directory to host our Django application and create a virtual environment inside that directory.
cd /home/dydeops/
mkdir myproject
cd myproject
virtualenv env
A virtual environment named env will be created. Let’s activate this virtual environment:
source env/bin/activate
Step 7 – Installing Django and gunicorn
pip install django gunicorn
This installs Django and gunicorn in our virtual environment
Step 8 – Possible Deployment Issues
To avoid deployment errors, we will take following actions:
Add allowed host, release media folder, run collectstatic and create requirements.txt from the local project.
ALLOWED_HOSTS = ['SERVER_IP_ADDRESS', 'localhost', '127.0.0.1']
Remove 'media' from .gitignore file
python manage.py collectstatic
pip freeze > requirements.txt
- Replace
psycopg2
package withpsycopg2-binary
- Install
backports.zoneinfo
only if the server python version is less than 3.9 backports.zoneinfo==0.2.1;python_version<"3.9"
- Add
gunicorn
to requirements.txt

Step 9 – Backup data from local machine and restore in to live database
python manage.py dumpdata > backup.json

Now check the remote directory, our project is pushed to the server. That’s all, we have set up Filezilla to upload the code from local machine to ftp server.
Open Django Project settings.py and check your project settings
cd /home/dydevops/myproject
cd myproject
sudo nano mwcshop/settings.py
In the myproject folder, activate virtual environment
source env/bin/activate
Install the packages from requirements.txt file
pip install -r requirements.txt
Run makemigrations and migrate commands
python manage.py migrate
Allow port 8000
sudo ufw allow 8000
Check status of ufw
sudo ufw status
Run the server
python manage.py runserver 0.0.0.0:8000
Remote server
python manage.py shell
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()
python manage.py loaddata backup.json
Configuring Gunicorn
Install Gunicorn on our server
if you are not install Gunicorn then install ..
sudo apt install gunicorn
Other wise run tell gunicorn to bind to our Django application and start running
gunicorn --bind 0.0.0.0:8000 mwcshop.wsgi
Test the link and make sure the site is working
exit
Go to this location and paste below code:
sudo nano /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Location
sudo nano /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=dydevops
Group=www-data
WorkingDirectory=/home/dydevops/myproject
ExecStart=/home/dydevops/myproject/env/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
mwcshop.wsgi:application
[Install]
WantedBy=multi-user.target
Restart and enable Gunicorn socket
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
Configuring Nginx as a reverse proxy
Location:
sudo nano /etc/nginx/sites-available/mwcshop
server {
listen 80;
server_name dydevops.com www.dydevops.com;
location ~ ^/.well-known {
root /home/dydevops/myproject;
allow all;
}
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/dydevops/myproject;
}
location /media/ {
root /home/dydevops/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
sudo ln -s /etc/nginx/sites-available/mwcshop /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Open port 80 and close 8000
sudo ufw allow 80
sudo ufw allow 'Nginx Full'
sudo ufw allow 586
sudo ufw deny 8000
Go to sites-enabled directory and delete the default site
cd /etc/nginx/sites-enabled/
ls
sudo rm default
Fix Static Files on Server
cd /etc/nginx/
ls
sudo nano nginx.conf

sudo systemctl restart nginx
Set Your domain name server
Open Django Project settings.py and check your project settings
cd myproject
sudo nano mwcshop/settings.py
ALLOWED_HOSTS = ['SERVER_IP_ADDRESS', 'www.dydevops.com', 'dydevops.com']
sudo service nginx restart
sudo service gunicorn restart
Install SSL
sudo apt install certbot python3-certbot-nginx
Verify certbot installation by running which certbot
sudo certbot --nginx -d www.dydevops.com