Support
Please support this website. Visit the Amazon using this affiliate link. There won't be any difference in your purchage, we will get some commission for every purchase you make.
Advertise with us
How to host Django application on DigitalOcean server using Gunicorn, Supervisor, and NGINX

Approx 5 years back, I wrote a small article on how to deploy a Django application on the PythonAnyWhere server for free.

https://pythoncircle.com/post/18/how-to-host-django-app-on-pythonanywhere-for-free/

In this article, we are going to see how to deploy a Django application on a DigitalOcean droplet.


(1) Setting up the server.

First, create an account on DigitalOcean. You will get $200 worth of credits which you can use to pay for server cost.

Once you have created the droplet, attach it to a floating IP address. A floating IP address is a non-changing IP4 address provided by DigitalOcean for each droplet.

Login to the server from your terminal using SSH.

Update the packages and install new packages.


Run the below commands.

apt-get update && apt-get upgrade


Check if the latest python is installed. If not, install python.

sudo apt-get install python3.10


Install essential Ubuntu Packages required to run the Django application. Like virtual environment, NGINX, MySQL, etc.

apt install virtualenv supervisor nginx mysql-server  python3-dev libmysqlclient-dev build-essential default-libmysqlclient-dev  net-tools plocate


If you are using MySQL DB in your Django application, setup the MySQL using mysql_secure_installation. Please refer to this article by DigitalOcean for the same.


Also, set the right timezone on the server.


(2) Project Setup

- Clone the git repository.

- Create the virtual environment. Activate it.

- Install the Django packages and dependencies in it from the requirement.txt file.

pip install -r requirement.txt

- Copy secret files manually.

- Open MySQL from the terminal and create the Database.

- Run migrate command, and create cache tables if any.

python manage.py migrate
python manage.py createcachetable

- Run collect static files command.

python manage.py collectstatic

- Install gunicorn 

pip install gunicorn



(3) Using Gunicorn 

Every Django application needs three things to work. A Web Server, an Application Server, and the application itself. You must know the difference between a web server and an application server.

A web server like NGINX takes care of HTTP requests and passes on only those requests which are meant for that application. Gunicorn is the application server here.

In the wsgi.py file of the Django application, an object is defined which is used by WSGI Server or Application Server, Gunicorn in this case.

application = get_wsgi_application()


WSGI stands for web server gateway interface. Check this https://peps.python.org/pep-3333/.

Gunicorn runs multiple instances of the Django application and distributes the incoming request load among those instances.


Now create a file named gunicorn_start in the project working directory, adjacent to manage.py file. Give it the executable permissions.

Copy and paste the below content into gunicorn_start file.


#!/bin/bash
NAME="myproject"
DIR=/home/myproject
USER=root
GROUP=root
WORKERS=2
BIND=unix:/home/myproject/gunicorn.sock
DJANGO_SETTINGS_MODULE=myproject.settings
DJANGO_WSGI_MODULE=myproject.wsgi
LOG_LEVEL=error

cd $DIR
source /home/virtualenvironments/myproject/bin/activate

export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
 --name $NAME \
 --workers $WORKERS \
 --user=$USER \
 --group=$GROUP \
 --bind=$BIND \
 --log-level=$LOG_LEVEL \
 --log-file=-

Let's understand the above file.

"myproject" is the name of the project.

"/home/myproject/" is the working directory of the project.

This file and the workers Gunicorn will spawn will run with the root user.

WORKERS=2 means that 2 worker threads of this application server will be there to handle the requests.

Communication will be via gunicorn.sock socket file.

Settting and wsgi file location is specified.

When this code is executed, it changes to working directory of project and activate the virtual environment from the location specified.



(4) Managing the Gunicorn process using supervisor

Copy and paste the below content into /etc/supervisor.conf file at the bottom.

[program:myproject]
command=/home/myproject/gunicorn_start
user=root
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/myproject/logs/gunicorn-error.log

This will keep the Gunicorn process up and running all the time.

Run the below supervisor commands to let the supervisor know of the above changes.

sudo supervisorctl reread. 
# output: myproject available

sudo supervisorctl update
# output: myproject added to process group

sudo supervisorctl status myproject
# Output:  myproject RUNNING 10s


Note that every time the application code is changed, we need to restart the supervisor myproject program (not the supervisor itself)

supervisorctl restart myprogram
# output
# myproject stopped
# myproject started


Check the Gunicorn error log file if program is not starting properly.



(5) Serving traffic via NGINX

So now our Django application is running via Gunicorn, which is handling the traffic using 2 worker threads. Gunicorn process is managed by Supervisor. Let's use a Domain to serve the traffic. 


Go to Godaddy or any other domain name provider and purchase a new domain. 


Go to the networking tab of DigitalOcean droplet settings. Go to domains. Add a new domain you just purchased. 

Add the A record for both, the domain and www subdomain.

Record - A
Host - @
Point to the IP of the droplet. TTL 3600 seconds.

Record - A
Host - www
Point to the IP of the droplet. TTL 3600 seconds.


Add three NS records.

Record - NS
Host - @
NS - ns1.digitalocean.com (and n2.digitalocean.com and ns3.digitalocean.com)

Now go to Godaddy.

In 'manage DNS' settings, edit and update the Nameservers. 


(6) NGINX config

Go to the NGINX configuration directory. Switch to sites-enabled directory and add a new file. Name it same as project name.

Copy and paste the below content in this conf file.

# accepts http and non-www version
server {
    server_name pythoncircle.com;
    # to avoid any error while fetching fevicon
    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/myproject;
    }

  # to serve media files
  location /media/ {
        root /homne/myproject/;
    }


    location / {
        include proxy_params;
        # communicate via socket file created by Gunicorn
        proxy_pass http://unix:/home/myproject/gunicorn.sock;
    }
}

Reload the NGINX server.

nginx -s reload

or

systemctl reload nginx


Now you should be able to access the Django project via DNS. In case of any issues, please check the NGINX and Supervisor logs.

Do not forget to add the DNS in allowed hosts property of project.


If NGINX is not able to connect to upstream i.e. gunicorn.sock (permission denied), it is because users of NGINX and gunicorn.conf might be different.
Run NGINX with root as well. change the user in nginx.conf file. reload NGINX.


Next, you might want to serve the traffic over HTTPS instead of HTTP. Check for SSL certificate installation for free using certbot.



(7) Security


Please make sure that in the firewall section of server settings, you have enabled only Ports 80 (HTTP traffic), 443 (HTTPS traffic) and 22 (SSH) for incoming traffic. You may open all ports of outgoing traffic based on your requirements.


As a good practice, you should not use passwords to SSH into the server. Use the public-private key combinations.

Also, create a separate user with only required permissions instead of working with the Root user.




Feel free to contact me in case if you are facing any issues in deploying the Django application on DigitalOcean.


Host your Django Application for free on PythonAnyWhere.
If you want complete control of your application and server, you should consider DigitalOcean. Create an account with this link and get $200 credits.



Feature Photo by Christina @ wocintechchat.com on Unsplash
0 comments on 'How To Host Django Application On Digitalocean Server Using Gunicorn, Supervisor, And Nginx'
Login to comment


Related Articles:
Using a custom domain for Django app hosted on AWS EC2
Using a custom domain for Django app hosted on AWS EC2, GoDaddy DNS with EC2 instance, Django App on EC2 with GoDaddy DNS, Using domain name in Nginx and EC2, Elastic IP and DNS on EC2...
AWS EC2 Vs PythonAnyWhere for hosting Django application
AWS EC2 Vs PythonAnyWhere for hosting Django application, hosting Django application for free on AWS EC2, Hosting Django application for free on PythonAnyWhere, comparing ec2 and pythonanywhere...
Hosting Django app for free on Amazon (AWS) EC2 with Gunicorn and Nginx
Step by step guide on hosting Django application on AWS ec2 instance, How to host the Django app on AWS ec2 instance from scratch, Django on EC2, Django app hosting on AWS, Free hosting of Django App...
Preventing cross-site scripting attack on your Django website
XSS attack in Django, preventing cross-site scripting attack in Django website, avoid XSS in Django application, Enabling SECURE_BROWSER_XSS_FILTER in Django website, blocking cross-site scripting attach on Django website...
DigitalOcean Referral Badge

© 2022-2023 Python Circle   Contact   Sponsor   Archive   Sitemap