5 Steps to deploy Django application using Nginx, Reverse Proxy and Gunicorn including SSL Certificate.

Saijal Shakya
5 min readJul 16, 2020

--

Deployment
Photo by Science in HD on Unsplash

Django is a free and open source web application framework, written in Python. A web framework is a set of components that helps you to develop websites faster and easier.

When you’re building a website, you always need a similar set of components: a way to handle user authentication (signing up, signing in, signing out), a management panel for your website, forms, a way to upload files, etc.

Luckily for you, other people long ago noticed that web developers face similar problems when building a new site, so they teamed up and created frameworks (Django being one of them) that give you ready-made components to use.

Frameworks exist to save you from having to reinvent the wheel and to help alleviate some of the overhead when you’re building a new site.

What is NGINX?

NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. In addition to its HTTP server capabilities, NGINX can also function as a proxy server for email (IMAP, POP3, and SMTP) and a reverse proxy and load balancer for HTTP, TCP, and UDP servers.

Reverse Proxy

One reason to proxy to other servers from Nginx is the ability to scale out your infrastructure. Nginx is built to handle many concurrent connections at the same time. This makes it ideal for being the point-of-contact for clients. The server can pass requests to any number of backend servers to handle the bulk of the work, which spreads the load across your infrastructure. This design also provides you with flexibility in easily adding backend servers or taking them down as needed for maintenance.

Proxying in Nginx is accomplished by manipulating a request aimed at the Nginx server and passing it to other servers for the actual processing. The result of the request is passed back to Nginx, which then relays the information to the client. The other servers in this instance can be remote machines, local servers, or even other virtual servers defined within Nginx. The servers that Nginx proxies requests to are known as upstream servers.

What is Gunicorn?

The Gunicorn “Green Unicorn” is a Python Web Server Gateway Interface (WSGI) HTTP server. It is a pre-fork worker model, ported from Ruby’s Unicorn project. The Gunicorn server is broadly compatible with a number of web frameworks, simply implemented, light on server resources and fairly fast.

Project and Server Setup

Step 1: Setting Django for deployment

First, clone your application to your webserver. Then:

Create, Activate and Install Dependencies in Virtual Environment

virtualenv venv
source venv/bin/activate
pip install -r requirements.txt

Important dependencies and changes in settings.py

pip install gunicorn

settings.py

DEBUG=False
ALLOWED_HOSTS = ['your_domain']

Collect your static files

python manage.py collectstatic

Step 2: Setting Gunicorn with systemd service file

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

Paste the following scripts in gunicorn.service

[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=saijalShakya
Group=www-data
WorkingDirectory=/home/saijalshakya/myproject
ExecStart=/home/saijalshakya/myproject/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bindunix:/home/saijalshakya/myproject/myproject.sock myproject.wsgi:application[Install]
WantedBy=multi-user.target

Section [Unit]:

This section is used to specify metadata and dependencies. We’ll put a description of our service here and tell the init system to only start this after the networking target has been reached

Section [Service]:

We’ll specify the user and group that we want to process to run under. We will give our regular user account ownership of the process since it owns all of the relevant files. We’ll give group ownership to the www-data group so that Nginx can communicate easily with Gunicorn.

Section [Install]:

This will tell systemd what to link this service to if we enable it to start at boot. We want this service to start when the regular multi-user system is up and running.

Now, we are ready to start our gunicorn service:

sudo systemctl start gunicorn
sudo systemctl enable gunicorn

Check status of process:

systemctl status gunicorn

To restart process:

systemctl restart gunicorn

We have set our django application and gunicorn service. Now at last we need to confiure nginx.

Step 3: Configure Nginx to Proxy Pass to Gunicorn

We will create our first server block config file by copying over the default file:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/yourDomain.com.confsudo nano /etc/nginx/sites-available/yourDomain.com.conf

Copy all the following scripts in yourDomain.com.conf

# NGINX server block
server {

server_name yourDomain.com www.yourDomain.com;

# Serve static files
location /static/ {
root /home/saijalshakya/myproject;
}

location / {
include proxy_params;
proxy_pass http://unix:/home/saijalshakya/myproject/myproject.sock;
}
}

Now that we have our server block files, we need to enable them. We can do this by creating symbolic links from these files to the sites-enabled directory, which Nginx reads from during startup.

We can create these links by typing:

sudo ln -s /etc/nginx/sites-available/yourDomain.com /etc/nginx/sites-enabled/

Next, test to make sure that there are no syntax errors in any of your Nginx files:

sudo nginx -t

If no problems were found, restart Nginx to enable your changes:

sudo systemctl restart nginx

Step 4: Configure SSL Certificate using CertBot

First, install certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx

Now, run following command to generate SSL Certificate

sudo certbot --nginx -d yourDomain.com -d www.yourDomain.com

By running above command, it will change come scripts written in our /etc/nginx/sites-available/yourDomain.com.conf

Now, lets force nginx to transfer http to https by adding following scripts in our yourDomain.com.conf file

# Force http to https
server {
server_name yourDomain.com www.yourDomain.com;
return 301 https://yourDomain.com$request_uri;
}

Finally, our /etc/nginx/sites-available/yourDomain.com.conf file looks like:

# Force http to https
server {
server_name yourDomain.com www.yourDomain.com;
return 301 https://yourDomain.com$request_uri;
}

# NGINX server block
server {

server_name yourDomain.com www.yourDomain.com;

# Serve static files
location /static/ {
root /home/saijalshakya/myproject;
}

location / {
include proxy_params;
proxy_pass http://unix:/home/saijalshakya/myproject/myproject.sock;
}
listen 80; # managed by Certbot listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/yourDomain.com/fullchain.pem;

ssl_certificate_key/etc/letsencrypt/live/yourDomain.com/privkey.pem;

include /etc/letsencrypt/options-ssl-nginx.conf;

ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

Last and Final Command sudo systemctl restart nginx

Step 5: Test your result

www.yourDomain.com

Thank You

--

--