sanjaysikdar.dev

Blog

HomeAboutTools
Sanjay Sikdar

Sanjay Sikdar

Software developer who enjoys developing software, solving challenges, and programming.

GithubLinkedInMain SiteSitemapRSS

© 2026 All rights reserved. Sanjay Sikdar

djangopythonapiubuntulinuxdeployment

Deploy Django / Django Rest Framework on Ubuntu 22.04 / 24.04

Sanjay Sikdar

Sanjay Sikdar

·Oct 17, 2023·6 min read

Today I'm gonna share how to Install and Configure Django / Django Rest Framework with Nginx and I am using AWS EC2 (t3.micro) for writing this tutorial.

Step 1 — Creating an EC2 Instance, DNS and SSH

First, we require an ec2 instance so launch an instance with your preferred size, you can also attach an Elastic IP to your instance.

In your DNS Server (Route 53 or Cloudflare) add these records.

Record NameRecord TypeValue
@A[Server_IP]
wwwCNAMEexample.com

Now, we have pointed from our DNS to our new server IP, now we need to log in into our new server using SSH client.

Example: ssh -i "YourKey.pem" ubuntu@SERVER_IP

Step 2 — Setup and Installing Requirements

Set a Timezone on Ubuntu:

bash
sudo timedatectl set-timezone Asia/Kolkata && sudo timedatectl

If first time using apt in this session, run the update command to update the package manager cache:

bash
sudo apt update && sudo apt -y upgrade

Install Basic Requirements:

bash
# Python 3.10
sudo apt install python3.10-venv -y && sudo apt install python3-pip -y && sudo apt install libpq-dev nginx curl
 
# Python 3.12
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get install python3.12-venv -y && sudo apt install python3-pip -y && sudo apt-get install python3-tk -y && sudo apt-get install python3.12-dev -y && sudo apt install libpq-dev nginx curl
 
# Python 3.14
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install -y python3.14 python3.14-venv python3.14-tk python3.14-dev \
    libpq-dev nginx curl
 
python3.14 -m ensurepip --upgrade
python3.14 -m pip install --upgrade pip setuptools wheel
 

After installing, you can request to your domain (http://example.com), You will get nginx default page as response.

Install Redis (optional)

bash
sudo apt install redis-server
sudo systemctl status redis
redis-cli ping 
 
# In not started 
sudo systemctl start redis
sudo systemctl enable redis

Step 3 — Creating a Database (Optional)

If you are using any third party database like RDS then you can skip this step.

Create a Postgres database for Django application; so execute the following command on command line to create database for Django / DRF app:

Installing Requirements:

bash
sudo apt install postgresql postgresql-contrib 
sudo -u postgres psql

Creating Database and User:

sql
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
\q

Step 4 — Install and Configure Django Project

Creating a new Django project or Clone from Github/GitLab

You can set up the git into your server following this Link (OPTIONAL)

Generate SSH Key on Server:

bash
ssh-keygen -o
 
cat /home/ubuntu/.ssh/id_rsa.pub # Ubuntu 22.04
 
cat /home/ubuntu/.ssh/id_ed25519.pub. # Ubuntu 24.04
  • How to Set Up SSH Keys on Ubuntu 22.04 / 24.04

Clone App from GitHub:

bash
cd /home/ubuntu
git clone https://github.com/sannjayy/drf-simple-task-tracker.git

Creating Virtual Environment and Setup Project Requirements:

bash
cd drf-simple-task-tracker
python3 -m venv zenv
source zenv/bin/activate
pip install -r requirements.txt
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py collectstatic

Make sure you have installed gunicorn and whitenoise in your env.

Testing Server:

bash
python manage.py runserver 0.0.0.0:8000

Request on http://example.com:8000

Step 5 — Setup Nginx & Gunicorn

You Can Generate All These Settings from Znas Tools

  • https://www.sanjaysikdar.dev/tools/nginx-config

Creatinggunicorn.socket

bash
sudo nano /etc/systemd/system/gunicorn.socket

Paste Following:

json
[Unit]
Description=gunicorn socket
 
[Socket]
ListenStream=/run/gunicorn.sock
 
[Install]
WantedBy=sockets.target

Creatinggunicorn.service

bash
sudo nano /etc/systemd/system/gunicorn.service

Replace theproject directory and project.wsgi location as your project name:

json
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
 
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/drf-simple-task-tracker
ExecStart=/home/ubuntu/drf-simple-task-tracker/zenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --timeout 600 \
          --bind unix:/run/gunicorn.sock \
          project.wsgi:application
 
[Install]
WantedBy=multi-user.target

Enable the Gunicorn:

bash
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
sudo systemctl status gunicorn.socket

Test Gunicorn:

bash
sudo systemctl status gunicorn
curl --unix-socket /run/gunicorn.sock localhost
sudo systemctl status gunicorn

Setup Nginx File

Replace theproject name as your project:

bash
sudo nano /etc/nginx/sites-available/project_name

Change the path/home/ubuntu/drf-simple-task-tracker and Copy, and paste the following Nginx Configuration:

json
server {
    server_name example.com www.example.com;
    client_max_body_size 100M;
    charset utf-8;
    underscores_in_headers on;
 
    # access_log /home/ubuntu/drf-simple-task-tracker/logs/nginx-access.log;
    error_log /home/ubuntu/drf-simple-task-tracker/logs/nginx-error.log;
 
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /home/ubuntu/drf-simple-task-tracker/static/staticfiles/;
    }
    location /media/ {
        root /home/ubuntu/drf-simple-task-tracker;
        client_max_body_size 100M;
    }
    location / {
        include proxy_params;
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;    
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Enable the configuration:

bash
sudo ln -s /etc/nginx/sites-available/project_name /etc/nginx/sites-enabled
 
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl status nginx

Now you can request domain http://example.com and your site should be visible.

Step 6 — Installing SSL

bash
sudo apt install certbot python3-certbot-nginx
 
sudo certbot --nginx -d example.com -d www.example.com
 
sudo systemctl status certbot.timer
sudo certbot renew --dry-run

Now you can request the website using https://example.com.

Creating Shell Script (Quick Actions) [OPTIONAL]

For restarting the Nginx and pulling Code from Git, I have created a shell script.

bash
sudo nano /usr/local/bin/z

For creating the shell script, modify copy, and paste the following code to your terminal.

bash
#!/bin/bash
select opt in Sync Restart ChangeDir CleanUp CheckStatus Quit
do
    case $opt in
    Sync)  
        cd /home/ubuntu/drf-simple-task-tracker
        git pull origin master
        echo "Code Synchronized!"
        exit 0
        ;;
    Restart)  
        sudo nginx -t && sudo systemctl restart nginx
        sudo systemctl restart gunicorn
        # sudo systemctl restart daphne.service
        echo "Nginx & gunicorn has been restarted."
        exit 0
        ;;
    ChangeDir)
        cd /home/ubuntu/drf-simple-task-tracker
        echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
        $SHELL
        exit 0
        ;;
        CleanUp)
            redis-cli flushall
            redis-cli flushdb 
            echo "Cleaned up Redis!"
           sudo apt clean
           sudo rm -rf /tmp/*
           sudo apt autoclean
           sudo rm /var/log/*.gz
           sudo journalctl --vacuum-size=50M
           sudo apt autoremove --purge
           echo "System Cleaned up"
        exit 0
            ;;
    CheckStatus)  
        echo "--> GUNICORN"    
        sudo systemctl status gunicorn
        echo "--> NGINX"    
        sudo systemctl status nginx
        echo "--> STORAGE"    
        df -h
        echo "--> Shell by SanjaySikdar.Dev <--"        
        exit 0
        ;;    
    Quit)
        echo "Exited!"
        exit 0
        ;;
    *)
        echo "invalid option"
        ;;
    esac
done
bash
sudo chmod +x /usr/local/bin/z

Now press the z key and hit enter.

bash
ubuntu@ip-172-31-0-94:~$ z
1) Sync
2) Restart
3) ChangeDir
4) CheckStatus
5) Quit
#?

Select any option by pressing the number keys.

Hope you guys like the article. If you encounter any difficulties in understanding this approach, please don't hesitate to leave a comment.

Enabling The ASGI (Optional)

Bind the port 9001

bash
daphne -b 0.0.0.0 -p 9001 project.asgi:application

Create Daphne Service

bash
sudo nano /etc/systemd/system/daphne.service
bash
[Unit]
Description=daphne service
After=network.target
 
[Service]
Type=simple
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/drf-simple-task-tracker
ExecStart=/home/ubuntu/drf-simple-task-tracker/zenv/bin/daphne -p 9001 project.asgi:application
Restart=on-failure
 
[Install]
WantedBy=multi-user.target

Start Service

bash
sudo systemctl daemon-reload
sudo systemctl start daphne.service
sudo systemctl status daphne.service
sudo systemctl enable daphne.service

Update Nginx File:

bash
# Place Here
upstream channels-backend {
    server localhost:9001;
}
server {
 
    location / { }
    # Place Here
    location /ws/ {
        proxy_pass http://0.0.0.0:9001;
        proxy_http_version 1.1;
        proxy_read_timeout 86400;
        proxy_redirect     off;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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-Host $server_name;
    }
}

Restart

bash
sudo systemctl restart daphne.service

Troubleshoot

If nginx getting 403-Forbidden > sudo gpasswd -a www-data ubuntu

Other Permission Issue > sudo chmod +x /home/ubuntu/projectdir

Restart Deamon > sudo systemctl daemon-reload

Installing mysqlclient - Click here

Generate SECRET_KEY > openssl rand -base64 64

Clean Up __pycache__ folders and migration files

bash
# Remove all __pycache__ directories
find . -type d -name "__pycache__" -exec rm -rf {} +
 
# Remove migration files except in the zenv folder
find . -type d -name zenv -prune -o -type f -path "*/migrations/*" ! -name "__init__.py" -exec rm -f {} +
Sanjay Sikdar

Written by Sanjay Sikdar

Software developer who enjoys developing software, solving challenges, and programming.