Django Deployment on VPS server

Shivangi
Django Unleashed
Published in
6 min readJan 18, 2024

Deploying a Django Application on a VPS Server with Gunicorn and Nginx

Introduction: Learn how to deploy your Django application on a remote VPS server using the Ubuntu terminal, with the assistance of Gunicorn and Nginx for optimal deployment.

Understanding Gunicorn: Gunicorn, short for Green Unicorn, serves as a Web Server Gateway Interface (WSGI), facilitating the flow of requests from clients to the web server and forwarding them to Python applications or web frameworks such as Flask or Django. This process ensures the execution of the relevant application code for each request, acting as a crucial bridge between your web server and web application.

Prerequisites for VPS Server Usage: Before proceeding, ensure that you have root access to your VPS server, along with the associated IP address and password. Connect to your server via SSH using the following command:

ssh root@<ip_address>

Enter your password when prompted.

Server Setup and Package Checks: Update and upgrade your server with the following commands:

sudo apt-get update
sudo apt-get upgrade

Verify the installation status of essential packages:

nginx -v
python --version # or python3 --version
pip --version
git --version

If any of these packages are not installed, use the following commands:

sudo apt install nginx
sudo apt install python3
sudo apt install python3-pip
sudo apt install git

Create a new user on the server instead of using the root user for deployment. This is a more professional and necessary step.

From the root user SSH terminal:

sudo adduser <new_user> # Example: sudo adduser shivangi

You will see output similar to the following:

Adding user `shivangi' ...
Adding new group `shivangi' (1001) ...
Adding new user `shivangi' (1001) with group `shivangi' ...
Creating home directory `/home/shivangi' ...
Copying files from `/etc/skel' ...
New password: <password>
Retype new password: <password>
passwd: password updated successfully
Changing the user information for shivangi
Enter the new value, or press ENTER for the default
Full Name []: shivangi
Room Number []: press enter
Work Phone []: press enter
Home Phone []: press enter
Other []:
Is the information correct? [Y/n] Y

To grant permissions similar to the root user for the new user, use the following command:

sudo usermod -aG sudo <new_user> # Example: sudo usermod -aG sudo shivangi

Exit from the root user terminal by typing:

root@vim_37671:~# exit

Now, log in via SSH using the new user (for this blog, “shivangi” is the new user):

ssh shivangi@<ip_address>

Replace <ip_address> with the actual IP address of your server. After logging in, you can use the pwd command to check that the /home/shivangi space has been created.

If you encounter an error like in future, install or wriet through sudo and get this error :

shivangi@vim_3767:~$ sudo apt install git
shivangi is not allowed to run sudo on this vim_name. This incident will be reported.

you can follow the guide provided by the your VPS provider

Popular VPS provider:
Amazon Web Services (AWS), DigitalOcean, Linode, Vultr, contabo etc.

Clone the Git Repository: Here are two methods for cloning a private repository, and I have provided the links below:

  1. Navigate to the working project directory, for example:
cd ~/project_folder_name

2. Create a virtual environment inside the folder with the desired name:

virtualenv env_name

3. Activate the virtual enviroment:

source env_name/bin/activate

Output look like this:

(env_name)shivangi@vim_3767:~/project_folder-name$ 

Install the necessary dependencies such as Redis, Celery, Matplotlib, Django, etc., that are required for the project.

(env_name)shivangi@vim_3767:~/project_folder-name$pip install django django-filter 

Install Gunicorn:

(env_name)shivangi@vim_3767:~/project_folder-name$pip install gunicorn
(env_name)shivangi@vim_3767:~/project_folder-name$deactivate
shivangi@vim_3767:~/project_folder-name$

Setting up Gunicorn and Nginx for a Successful Server Run

Create a System Socket File for Gunicorn:

Replace “your_domain” with a name related to the project_folder_name for relevance. Use the same name when specifying your_domain.

  1. Open the socket file with the nano text editor:
shivangi@vim_3767:~$ sudo nano /etc/systemd/system/your_domain.gunicorn.socket

2. Write below code inside your_domain.gunicorn.socket File:

[Unit]
Description=your_domain.gunicorn socket

[Socket]
ListenStream=/run/your_domain.gunicorn.sock

[Install]
WantedBy=sockets.target

3. Create System Service File for Gunicorn:

shivangi@vim_3767:~$ sudo nano /etc/systemd/system/your_domain.gunicorn.service

4. Write below code inside your_domain.gunicorn.service File:

[Unit]
Description=your_domain.gunicorn daemon
Requires=your_domain.gunicorn.socket
After=network.target

[Service]
User=username
Group=groupname
WorkingDirectory=/home/shivangi/project_folder_name
ExecStart=/home/shiavngi/project_folder_name/env_name/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/your_domain.gunicorn.sock \
inner_project_folder_name.wsgi:application

[Install]
WantedBy=multi-user.target

Ensure to replace “username,” “groupname,” “project_folder_name,” “virtual_env_name,” and “inner_project_folder_name” with the appropriate values for your setup.

Start the Socket and Service File & Enable Gunicorn Socket and Service:

shivangi@vim_3767:~$ sudo systemctl start your_domain.gunicorn.socket
shivangi@vim_3767:~$ sudo systemctl start your_domain.gunicorn.service
shivangi@vim_3767:~$ sudo systemctl enable your_domain.gunicorn.socket
shivangi@vim_3767:~$ sudo systemctl enable your_domain.gunicorn.service

check the active status of the both socket and service files:

shivangi@vim_3767:~$ sudo systemctl status sonamkumari.com.gunicorn.socket
shivangi@vim_3767:~$ sudo systemctl status sonamkumari.com.gunicorn.service

output file:

Restart Gunicorn (You may need to restart everytime you make change in your project code)

shivangi@vim_3767:~$ sudo systemctl daemon-reload
shivangi@vim_3767:~$ sudo systemctl restart your_domain.gunicorn

Setting up Nginx File Support

  1. Create a Virtual Host File:
    You can specify another name in place of “your_domain” in the Nginx settings that are relevant to the project, but I will use the same.
shivangi@vim_3767:~$ sudo nano /etc/nginx/sites-available/your_domain

2. Write the Following Code in the Virtual Host File:

server{
listen 80;
listen [::]:80;

server_name your_domain www.your_domain;

location = /favicon.ico { access_log off; log_not_found off; }

location / {
proxy_set_header Host $http_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;
proxy_pass http://unix:/run/your_domain.gunicorn.sock;
}

location /static/ {
root /var/www/project_folder_name;
}

location /media/ {
root /var/www/project_folder_name;
}
}

3. Enable the Virtual Host or Create a Symbolic Link of the Virtual Host File:

shivangi@vim_3767:~$ sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/your_domain

4. Check if the Configuration is Correct or Not & Allow Traffic on Port 80 and Restart Nginx:

shivangi@vim_3767:~$ sudo nginx -t
shivangi@vim_3767:~$ sudo ufw allow 80
shivangi@vim_3767:~$ sudo service nginx restart

Make Changes to your Project Directory

Create the Folder in /var/www/:

shivangi@vim_3767:~$ cd /var/www
shivangi@vim_3767:~$ sudo mkdir project_folder_name
shivangi@vim_3767:~$ cd project_folder_name
shivangi@vim_3767:~$ sudo mkdir static media

Ensure to replace “your_domain” and “project_folder_name” with your actual domain and project folder names.

Give the permission to the directory /var/www/report

shivangi@vim_3767:~$ cd /var/www
shivangi@vim_3767:/var/etc$ sudo chown -R user:user project_folder_name

If you want to use Development’s Media Files, then move development’s media files to the public directory (Optional):

shivangi@vim_3767:~$ cd ~/project_folder_name
shivangi@vim_3767:~/project_folder-name$ sudo mv media/* /var/www/project_folder_name/media/

Open Django Project settings.py:

shivangi@vim_3767:~$cd ~/project_folder_name/inner_project_folder_name
shivangi@vim_3767:~/project_folder-name/inner_porject_folder_name$ nano settings.py

Make the following changes:

DEBUG = False
STATIC_URL = 'static/'
STATIC_ROOT = "/var/www/miniblog/static/"
MEDIA_URL = '/media/'
MEDIA_ROOT = "/var/www/miniblog/media/"

Restart Gunicorn (You need to restart every time you make a change in your project code):

shivangi@vim_3767:~/project_folder-name$ sudo systemctl daemon-reload
shivangi@vim_3767:~/project_folder-name$ sudo systemctl restart your_domain.gunicorn
# This restarts the socket and service files

Activate the project folder directory:

shivangi@vim_3767:~/project_folder-name$ source env_name/bin/activate

The prompt should change to (env_name)shivangi@vim_3767:~/project_folder-name$

Serve Static Files

shivangi@vim_3767:~/project_folder-name$ python manage.py collectstatic

Create Database Tables

shivangi@vim_3767:~/project_folder-name$ python manage.py makemigrations
shivangi@vim_3767:~/project_folder-name$ python manage.py migrate

Create Superuser

shivangi@vim_3767:~/project_folder-name$ python manage.py createsuperuser

If needed Deactivate Virtual env

shivangi@vim_3767:~/project_folder-name$ deactivate

Restart Gunicorn (You may need to restart everytime you make change in your project code)

sudo systemctl daemon-reload
sudo systemctl restart your_domain.gunicorn

Restart Nginx

sudo service nginx restart

Ensure to replace placeholders such as project_folder_name, inner_project_folder_name, env_name, and others with your actual values.

Certainly! If you face difficulties during deployment, feel free to comment here for assistance. However, for privacy and security reasons, please refrain from sharing personal contact information or social media account links in public forums. I’m here to help within the context of this conversation.

--

--

Shivangi
Django Unleashed

Enjoy Coding, Free solution and code and error solving, Follow the articles.