Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu 20.04

rettx

Arctype Team

Posted on June 29, 2021

Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu 20.04

feature_image.jpeg

Introduction


Django is an open-source Python framework that can be used for deploying Python applications. It comes with a development server to test your Python code in the local system. If you want to deploy a Python application on the production environment then you will need a powerful and more secure web server. In this case, you can use Gunicorn as a WSGI HTTP server and Nginx as a proxy server to serve your application securely with robust performance.

Prerequisites

  • A server running Ubuntu 20.04.
  • A valid domain name pointed with your server IP.
  • A root password is configured on your server.

Install Required Packages


First, you will need to install Nginx and other Python dependencies on your server. You can install all the packages with the following command:

apt-get install python3-pip python3-dev libpq-dev curl nginx -y

Once all the packages are installed, start the Nginx service and enable it to start at system reboot:

systemctl start nginx


systemctl enable nginx

Install and Configure PostgreSQL


Next, you will need to install the PostgreSQL server on your server. You can install it with the following command:

apt-get install postgresql postgresql-contrib -y

After the installation, log in to PostgreSQL shell with the following command:

su - postgres
psql
Enter fullscreen mode Exit fullscreen mode

Next, create a database and user for Django with the following command:

CREATE DATABASE 
    djangodb;
CREATE USER 
    djangouser 
    WITH PASSWORD 'password';   
Enter fullscreen mode Exit fullscreen mode


Next, grant some required roles with the following command:

ALTER ROLE djangouser 
    SET client_encoding 
    TO 'utf8';
ALTER ROLE djangouser 
    SET default_transaction_isolation 
    TO 'read committed';
ALTER ROLE djangouser 
    SET timezone 
    TO 'UTC';
GRANT ALL PRIVILEGES 
    ON DATABASE djangodb 
    TO djangouser;
Enter fullscreen mode Exit fullscreen mode

Next, exit from the PostgreSQL shell using the following command:

\qexit

Create a Python Virtual Environment


Next, you will need to create a Python virtual environment for the Django project.

First, upgrade the PIP package to the latest version:

pip3 install --upgrade pip

Enter fullscreen mode Exit fullscreen mode

Next, install the virtualenv package using the following command:

pip3 install virtualenv
Enter fullscreen mode Exit fullscreen mode

Next, create a directory for the Django project using the command below:

mkdir ~/django_project
Enter fullscreen mode Exit fullscreen mode

Next, change the directory to django_project and create a Django virtual environment:

cd ~/django_project
virtualenv djangoenv
Enter fullscreen mode Exit fullscreen mode


Next, activate the Django virtual environment:

source djangoenv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Next, install the Django, Gunicorn, and other packages with the following command:

pip install django gunicorn psycopg2-binary
Enter fullscreen mode Exit fullscreen mode

Install and Configure Django


Next, run the following command to create a Django project:

django-admin.py startproject django_project ~/django_project
Enter fullscreen mode Exit fullscreen mode

Next, edit the settings.py and define your database settings:

nano ~/django_project/django_project/settings.py
Enter fullscreen mode Exit fullscreen mode


Find and change the following lines:

ALLOWED_HOSTS = ['django.example.com', 'localhost']
DATABASES = {  
     'default': {     
     'ENGINE': 'django.db.backends.postgresql_psycopg2',       
     'NAME': 'djangodb',       
     'USER': 'djangouser',        
     'PASSWORD': 'password',        
     'HOST': 'localhost',       
     'PORT': '',    
   }
}
STATIC_URL = '/static/'
import os
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Enter fullscreen mode Exit fullscreen mode

Save and close the file then migrate the initial database schema to the PostgreSQL database:

./manage.py makemigrations
./manage.py migrate
Enter fullscreen mode Exit fullscreen mode

Next, create an admin user with the following command:

./manage.py createsuperuser
Enter fullscreen mode Exit fullscreen mode

Set your admin username and password as shown below:

Username (leave blank to use 'root'): admin
Email address: admin@example.com
Password: 
Password (again): 
Superuser created successfully.
Enter fullscreen mode Exit fullscreen mode

Next, gather all the static content into the directory

./manage.py collectstatic
Enter fullscreen mode Exit fullscreen mode

Test the Django Development Server


Now, start the Django development server using the following command:

./manage.py runserver 0.0.0.0:8000
Enter fullscreen mode Exit fullscreen mode

You should see the following output:

Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
June 22, 2021 - 11:15:57
Django version 3.2.4, using settings 'django_project.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
Enter fullscreen mode Exit fullscreen mode

Now, open your web browser and access your Django app using the URL http://django.example.com:8000/admin/. You will be redirected to the Django login page:

django admin login page

Provide your admin username, password and click on the Login. You should see the Django dashboard on the following page:

django admin dashboard

Now, go back to your terminal and press CTRL + C to stop the Django development server.

Test Gunicorn


Next, you will need to test whether the Gunicorn can serve the Django or not. You can start the Gunicorn server with the following command:

 gunicorn --bind 0.0.0.0:8000 django_project.wsgi
Enter fullscreen mode Exit fullscreen mode


If everything is fine, you should get the following output:

[2021-06-22 11:20:02 +0000] [11820] [INFO] Starting gunicorn 20.1.0
[2021-06-22 11:20:02 +0000] [11820] [INFO] Listening at: http://0.0.0.0:8000 (11820)
[2021-06-22 11:20:02 +0000] [11820] [INFO] Using worker: sync
[2021-06-22 11:20:02 +0000] [11822] [INFO] Booting worker with pid: 11822
Enter fullscreen mode Exit fullscreen mode

Press CTRL + C to stop the Gunicorn server.

Next, deactivate the Python virtual environment with the following command:

deactivate
Enter fullscreen mode Exit fullscreen mode

Create a Systemd Service File for Gunicorn


It is a good idea to create a systemd service file for the Gunicorn to start and stop the Django application server.

To do so, create a socket file with the following command:

nano /etc/systemd/system/gunicorn.socket
Enter fullscreen mode Exit fullscreen mode


Add the following lines:

[Unit]
Description=gunicorn socket
[Socket]ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Enter fullscreen mode Exit fullscreen mode

Save and close the file then create a service file for Gunicorn:

nano /etc/systemd/system/gunicorn.service
Enter fullscreen mode Exit fullscreen mode

Add the following lines that match your Django project path:

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/root/django_project
ExecStart=/root/django_project/djangoenv/bin/gunicorn --access-logfile - --workers 3 --bind 
unix:/run/gunicorn.sock          django_project.wsgi:application
[Install]
WantedBy=multi-user.target  
Enter fullscreen mode Exit fullscreen mode

Save and close the file then set proper permission to the Django project directory:

chown -R www-data:root ~/django_project
Enter fullscreen mode Exit fullscreen mode

Next, reload the systemd daemon with the following command:

systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

Next, start the Gunicorn service and enable it to start at system reboot:

systemctl start gunicorn.socket
systemctl enable gunicorn.socket
Enter fullscreen mode Exit fullscreen mode

To check the status of the Gunicorn, run the command below:

systemctl status gunicorn.socket
Enter fullscreen mode Exit fullscreen mode


You should get the following output:

● gunicorn.socket - gunicorn socket     
Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled)     
Active: active (running) since Tue 2021-06-22 12:05:05 UTC; 3min 7s ago   Triggers: ● gunicorn.service     
Listen: /run/gunicorn.sock (Stream)     
CGroup: /system.slice/gunicorn.socket
Jun 22 12:05:05 django systemd[1]: Listening on gunicorn socket.
Enter fullscreen mode Exit fullscreen mode

Configure Nginx as a Reverse Proxy to Gunicorn Application


Next, you will need to configure Nginx as a reverse proxy to serve the Gunicorn application server.

To do so, create an Nginx configuration file:

nano /etc/nginx/conf.d/django.conf
Enter fullscreen mode Exit fullscreen mode

Add the following lines:

   server {  
    listen 80;     
    server_name django.example.com;    
    location = /favicon.ico { access_log off; log_not_found off; }    
    location /static/ {         
        root /root/django_project;     
    }    
    location / {         
        include proxy_params;         
        proxy_pass http://unix:/run/gunicorn.sock;     
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and close the file then verify the Nginx for any configuration error:

nginx -t
Enter fullscreen mode Exit fullscreen mode

Output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

Finally, restart the Nginx service to apply the changes:

systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode


Now, you can access the Django application using the URL http://django.example.com/admin.

Conclusion


In the above guide, you learned how to deploy a Django application with Gunicorn and Nginx as a reverse proxy. You can now use this setup in the production environment for deploying secure and high-performance Python applications.

Featured image by Gerry Sabar: https://gerrysabar.medium.com/deploying-django-3-nginx-postgre-to-ubuntu-18-04-vps-220c529b588

💖 💪 🙅 🚩
rettx
Arctype Team

Posted on June 29, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related