ARTICLE

How to Deploy Django App on Cloud Raya VM Using Gunicorn, Supervisor, and Nginx

11 June 2022 by Muhammad Ahfas An Nahri

A basic guide on how to deploy Django app, using Gunicorn, Supervisor, and Nginx stack on your Cloud Raya VM instance.

In this article, I will be using Ubuntu 22.04 LTS as the deployment server, Python 3.8 and Django 4.0.

TLDR

  1. Create a standard user called apps
  2. Install supervisor and nginx
sudo apt install supervisor nginx -y
  1. Install your App’s Python version.
  2. Install pip
  3. Install pipenv globally.
sudo pip install pipenv
  1. Add your server IP and/or FQDN address to ALLOWED_HOSTS in settings.py file
ALLOWED_HOSTS = [ "xx.yy.dd.zz", "your.domain.tld" ]
  1. Copy the django app to /home/apps/django-app
  2. Go to the app folder and run:
cd /home/apps/django-app
python3.8 -m pipenv install --deploy
  1. Install Gunicorn using pipenv on the same directory
python3.8 -m pipenv install gunicorn
  1. Create supervisor config file under /etc/supervisor/conf.d/django-app.conf
[program:django-app]
user=apps
directory=/home/apps/django-app/djangoapp/
command=/usr/local/bin/pipenv run gunicorn --workers=3 djangoapp.wsgi

autostart=true
autorestart=true
stdout_logfile=/home/apps/logs/django-app.log
stderr_logfile=/home/apps/logs/django-app.err.log
  1. Create the required files and folder:
mkdir /home/apps/logs/
touch /home/apps/django-app{,.err}.log
  1. Restart supervisor to recognize the app
sudo systemctl restart supervisor
  1. Create nginx server block file for the app under /etc/nginx/sites-available/django-app.conf
server {
    listen 80;
    
    location / {
        include proxy_params;
        proxy_pass http://localhost:8000;
    }
}
  1. Activate the config and reload nginx
sudo ln -s /etc/nginx/sites-available/django-app.conf /etc/nginx/sites-enabled
sudo unlink /etc/nginx/sites-enabled/default
sudo nginx -t
sudo nginx -s reload
  1. Access the app from your browser: http://your-ip or http://your-domain.tld and DONE!

Step-by-step Guide

Django App Peparation

I will assume that your Django App is ready to be deployed. This means it has Pipfile or requirements.txt. For this tutorial, I’m going to use pipenv as the virtual environment tool and here’s the directory structure of the app:

├── djangoapp
│   ├── db.sqlite3
│   ├── djangoapp
│   │   ├── asgi.py
│   │   ├── __init__.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── manage.py
├── Pipfile
└── Pipfile.lock

Make sure the app runs successfully in our local environment by running the below command on the app directory:

pipenv run djangoapp/manage.py runserver

Then access your browser with http://127.0.0.1:8000

Add your server IP and/or domain to ALLOWED_HOST entry in the settings.py file, then save it.

Allowed hosts configuration

Good, now we are ready to do the deployment.

Server Preparation

We will need a specific user that we will use to serve the app, and it should be a non administrative user. To simplify, we will create apps user

sudo useradd --create-home --shell /bin/bash apps

We will also want to install supervisor and nginx from now

sudo apt update && sudo apt install supervisor nginx

As mentioned earlier, we will be using Python 3.8 which isn’t available by default, so please take a look at this article on how to install Python 3.8 on Ubuntu 22.04 Jammy. Don’t forget to install pip as well.

Then install pipenv globally:

sudo pip install pipenv
Installing pipenv

Copy App Files

Copy or clone (using git if it’s supported) the app files to /home/apps/django-app. You can use FTP, SFTP, SCP or any other means of transferring local files to the remote server. On the remote server, the apps directory should look like follows:

django-app folder structure

Install Required Dependencies

A good thing about pipenv is that it will automatically creates a virtual environment upon installing any required dependencies listed in the Pipfile. So, on the django-app folder run:

# make sure it's on /home/apps/django-app
python3.8 -m pipenv install --deploy

Next, we will install gunicorn:

python3.8 -m pipenv install gunicorn

Then, we will try to serve the app using gunicorn to test, but make sure you run the gunicorn from the app folder where manage.py resides:

cd djangoapp/
python3.8 -m pipenv run gunicorn djangoapp.wsgi

It should return something like this:

Serving django via gunicorn

Awesome. Now we can setup supervisor to handle gunicorn process(es).

Install and Configure Supervisor

For Debian-based distros, run:

sudo apt install supervisor

For RHEL-based distros, run:

sudo dnf install supervisor
# or
sudo yum install supervisor

Then, we will create a config file for the django app in /etc/supervisor/conf.d/ and name it as django-app.conf. Write or just copy the following lines to the file:

[program:django-app]
user=apps
directory=/home/apps/django-app/djangoapp
command=/usr/local/bin/pipenv run gunicorn --workers=3 djangoapp.wsgi

autostart=true
autorestart=true
stdout_logfile=/home/apps/logs/django-app.log
stderr_logfile=/home/apps/logs/django-app.err.log

Don’t forget to create the ./logs/ folder to store the app’s logs:

# as the apps user
mkdir /home/apps/logs

Then restart supervisor:

sudo systemctl restart supervisor

Make sure it’s running by checking supervisor status:

sudo systemctl status supervisor
Supervisor status

Next, we will install Nginx and configure it so it proxies the connection.

Install and Configure NGINX

Here, nginx will proxy HTTP connections to the gunicorn workers. This will also make SSL setup easier, but I won’t explain it here. Install nginx and make sure it’s started on boot:

sudo apt install nginx
sudo systemctl enable nginx --now

Then create a new config file in /etc/nginx/sites-available for Ubuntu-based distros, RHEL-based ones should be in /etc/nginx/conf.d

server {
    listen 80;
    
    location / {
        include proxy_params;
        proxy_pass http://localhost:8000;
    }
}

Save it as django-app.conf. Then for Ubuntu-based distro only, create a symlink in /etc/nginx/sites-enabled/ for the config file:

sudo ln -s /etc/nginx/sites-available/django-app.conf /etc/nginx/sites-enabled/django-app.conf

Remove the default site config

sudo unlink /etc/nginx/sites-enabled/default

For RHEL-based distros, one might need to remove the default config or just rename the extension to .bak or something else. Then, test nginx and reload it

sudo nginx -t
sudo nginx -s reload

Access Test

Finally, test it from your browser via http://YOUR-IP or http://YOUR-DOMAIN.TLD

Yay! You’re now able to deploy your django app!

IMPORTANT NOTE: This is a basic setup which is insecure. A complete documentation on how to configure your django so it fits production deployment, please refer to this official documentation

Conclusion

We just learned how to deploy a django application using Pipenv as the virtual environment tool, Gunicorn as the Web Server Gateway, Supervisor as the process manager and finally, NGINX as the reverse proxy.

Find more tutorial articles in Cloud Raya’s Knowledge Base, or if you need article with more general topics about technology, feel free to visit our Blog. Even better, register now for free in Cloud Raya’s panel to try our overall products.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Ready to Make Something Big?

Deploy in Cloud Raya
Background wave