In this post, we will see how to use nginx with gunicorn to serve django applications in production.
Django is a very powerful web framework and ships with a server which is able to facilitate development. This development server is not scalable and is not suited for production. Hence we need to configure gunicorn to get better scalability and nginx can be used as a reverse proxy and as a web server to serve static files. Let’s get started
Before you follow the steps outlined below, I will assume that you have already configured your Ubuntu server with a non root user and firewall as outlined here.
Step 1 – Installing python and nginx
Let’s update the server’s package index using the command below:
1 |
sudo apt update |
Step 2 – Install Nginx
Install Nginx using the command below:
1 |
sudo apt install nginx |
Step 3 – Allow Nginx through the firewall
Allow Nginx through the firewall using the command below:
1 2 |
sudo ufw app list sudo ufw allow 'Nginx Full' |
Step 4 – Install & Configure PostgreSQL
Let’s install PostgreSQL using the command below:
While you are logged into the server, run following commands to install, start, enable and see the status of postgresql database:
1 2 3 4 |
sudo apt-get install postgresql postgresql-contrib sudo systemctl start postgresql.service sudo systemctl enable postgresql.service sudo systemctl status postgresql.service |
Step 5 -Postgres Database & User Setup
1 |
sudo -u postgres psql |
You should now be logged into the pg shell
Create a database
1 |
CREATE DATABASE dydevops_db; |
Create user
1 |
CREATE USER dbmwshop WITH PASSWORD 'MaWbc1$23!'; |
Set default encoding, tansaction isolation scheme (Recommended from Django)
1 2 3 |
ALTER ROLE dbmwshop SET client_encoding TO 'utf8'; ALTER ROLE dbmwshop SET default_transaction_isolation TO 'read committed'; ALTER ROLE dbmwshop SET timezone TO 'UTC'; |
Give User access to database
1 |
GRANT ALL PRIVILEGES ON DATABASE dydevops_db TO dbmwshop; |
Quit out of Postgres
1 |
\q |
Step 6 – Installing python and nginx
Let’s update the server’s package index using the command below:
1 |
sudo apt install python3-pip python3-dev nginx |
This will install python, pip and nginx server
Step 7 – Creating a python virtual environment
1 |
sudo pip3 install virtualenv |
This will install a virtual environment package in python. Let’s create a project directory to host our Django application and create a virtual environment inside that directory.
1 2 3 |
cd /home/dydeops/ mkdir myproject cd myproject |
1 |
virtualenv env |
A virtual environment named env will be created. Let’s activate this virtual environment:
Step 10 – Backup data from local machine and restore in to live database
1 |
python manage.py dumpdata > backup.json |
Now check the remote directory, our project is pushed to the server. That’s all, we have set up Filezilla to upload the code from local machine to ftp server.
Open Django Project settings.py and check your project settings
cd /home/dydevops/myproject
1 2 |
cd myproject sudo nano mwcshop/settings.py |
In the myproject folder, activate virtual environment
1 |
source env/bin/activate |
Install the packages from requirements.txt file
1 |
pip install -r requirements.txt |
Run makemigrations and migrate commands
1 |
python manage.py migrate |
Allow port 8000
1 |
sudo ufw allow 8000 |
Check status of ufw
1 |
sudo ufw status |
Run the server
1 |
python manage.py runserver 0.0.0.0:8000 |
Remote server
1 2 3 4 5 |
python manage.py shell from django.contrib.contenttypes.models import ContentType ContentType.objects.all().delete() quit() python manage.py loaddata backup.json |
Configuring Gunicorn
Install Gunicorn on our server
if you are not install Gunicorn then install ..
1 |
sudo apt install gunicorn |
Other wise run tell gunicorn to bind to our Django application and start running
1 |
gunicorn --bind 0.0.0.0:8000 mwcshop.wsgi |
Test the link and make sure the site is working
exit
Go to this location and paste below code:
1 |
sudo nano /etc/systemd/system/gunicorn.socket |
1 2 3 4 5 6 |
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target |
Location:
1 |
sudo nano /etc/systemd/system/gunicorn.service |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=dydevops Group=www-data WorkingDirectory=/home/dydevops/myproject ExecStart=/home/dydevops/myproject/env/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ mwcshop.wsgi:application [Install] WantedBy=multi-user.target |
Restart and enable Gunicorn socket
1 2 |
sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket |
Configuring Nginx as a reverse proxy
Location:
1 |
sudo nano /etc/nginx/sites-available/mwcshop |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server { listen 80; server_name dydevops.com www.dydevops.com; location ~ ^/.well-known { root /home/dydevops/myproject; allow all; } location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/dydevops/myproject; } location /media/ { root /home/dydevops/myproject; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } |
1 2 |
sudo ln -s /etc/nginx/sites-available/mwcshop /etc/nginx/sites-enabled/ sudo systemctl restart nginx |
Open port 80 and close 8000
1 2 3 4 |
sudo ufw allow 80 sudo ufw allow 'Nginx Full' sudo ufw allow 586 sudo ufw deny 8000 |
Go to sites-enabled directory and delete the default site
1 2 3 |
cd /etc/nginx/sites-enabled/ ls sudo rm default |
Fix Static Files on Server
1 2 3 |
cd /etc/nginx/ ls sudo nano nginx.conf |
1 |
sudo systemctl restart nginx |
Set Your domain name server
Open Django Project settings.py and check your project settings
1 2 |
cd myproject sudo nano mwcshop/settings.py |
1 |
ALLOWED_HOSTS = ['SERVER_IP_ADDRESS', 'www.dydevops.com', 'dydevops.com'] |
1 2 |
sudo service nginx restart sudo service gunicorn restart |
Install SSL
1 |
sudo apt install certbot python3-certbot-nginx |
Verify certbot installation by running which certbot
1 |
sudo certbot --nginx -d www.dydevops.com |