5 Steps to deploy Django application using Nginx, Reverse Proxy and Gunicorn including SSL Certificate.
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/myprojectExecStart=/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