Deploying your django application in Cpanel

One of the old fear among developers is deploying the application in a production environment from development environment. In this tutorial, we will overcome that fear by deploying our Django application in Cpanel.

Cpanel is the ideal choice for newcomers who are just stepping their foot into the cloud. In this tutorial, we will also look at how you can manage your Django static and media assets in production sever without banging your head for hours.

After completion of this tutorial, you will be able to;

  • deploy your Django application in Cpanel

  • manage static and media assets in the production server

  • manage credentials and secret key in production

Table of Content

  1. Prerequisites

  2. Installing gunicorn to serve Django app in production

  3. Installing whitenoise for serving static files in production

  4. Setting up the Django app for deployment

  5. Moving Django application to the Cpanel

  6. Creating a new python application in Cpanel

  7. Installing dependencies

  8. Configuring passenger_wsgi.py

  9. Managing database

  10. Creating a new separate subdomain to serve media files

  11. Managing application secrets and database credentials

  12. Wrapping up

Prerequisites

Alright, I assume you already have a production-ready Django application running in your development server along with static assets in the static folder and user-uploaded media files in the media folder.

I am going to use geekydocs as my project name, make sure you replace this name with your actual Django project name while writing code and running commands.

Project Structure

Here is the screenshot of the basic Django project.

Installing gunicorn to serve django app in production

In the production environment, we don't use a Django development server. The one that you run using  python manage.py runserver command.

For production, we need a powerful server which can handle many concurrent access to our application. So for that, we are going to use gunicorn. gunicorn is a pure-Python WSGI server and can be installed using pip.

Open up the new terminal window and run the following command. It will install the latest version of gunicorn in your machine.

$ pip install gunicorn

now, you can run your application using the gunicorn,. As an argument, pass the wsgi file of the django application.

$ gunicorn geekydocs.wsgi

Replace geekydocs with your Django project name. It will start the server on which you can visit from your browser.

Installing whitenoise for serving static files in production

Django by default doesn't support static file serving in a production environment. For this reason, we have to use a third-party library called whitenoise

First of all, let's collect the static files of our Django application.

$ python manage.py collectstatic

Then, install whitenoise using pip

$ pip install whitenoise

Now, let's edit the settings.py file and add WhiteNoise to the MIDDLEWARE list. Make sure, it comes after SecurityMiddleware

MIDDLEWARE = [
    # ...
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    # ...
]

Now the final step, we have to wrap up Whitenoise on the wsgi.py file. So that, it will serve static assets in the production server.

Open up wsgi.py file and wrap up the existing wsgi application with Whitenoise

import os

from django.core.wsgi import get_wsgi_application

# importing whitenoise
from whitenoise import WhiteNoise

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "geekydocs.settings")

application = get_wsgi_application()

# wrapping up existing wsgi application
application = WhiteNoise(application, root="static")

Setting up the Django application for deployment

Now, we have to make a couple of changes in settings.py before moving our application to Cpanel.

First, change the debug mode to False

DEBUG = False

then change ALLOWED_HOSTS to your host domain

ALLOWED_HOSTS = ["example.com", "www.example.com", "https://example.com"]

Finally, export the project dependencies into requirements.txt. So that, we can later install them in production.

pip freeze > requirements.txt

Moving Django application to the Cpanel

Now, let's move our Django application from the development environment to the Cpanel

We have two options here;

  1. Create a GitHub repository where we will push our code from the development machine and will pull it from Cpanel

  2. Archive our Django application as a zip file and upload it to the Cpanel and later on we can extract and run it

In this tutorial, we will follow step no 1, as it will be more efficient over time and we won't have to archive and unarchive our app frequently.

To follow step 2, you have to do the initial set-up first;

  1. Create a new GitHub repository to your account for the project

  2. Commit the changes and push it to the GitHub

  3. Connect GitHub with SSH in the production server, in this case, Cpanel. You can follow this guide to connect GitHub with SSH.

Alright, I assume you did the initial set up and pushed your final production code to the GitHub.

Now, copy the repository URL from Github

Cloning repo

Then, log in to the Cpanel and open up a terminal

Opening Terminal

Clone the repository using the command git clone. As an argument pass the repository URL that you copied earlier

$ git clone git@github.com:chapainaashish/geekydocs.git

It will clone the repository to your root directory and the folder name will be your project name. Here, in my case, it will be geekydocs

Remember this folder name, we will need this later on while creating a Python application.

Creating a new python application in Cpanel

We have successfully moved our Django application to Cpanel using git now it's time to create a new Python application to run that code.

Open up a Setup Python App tool in Cpanel

Creating Python application

Then, click on Create application

Creating Python application

It will load a form where we have to configure our application.

Creating Python application

Let's configure our Python application step by step;

First of all, choose the python version that you have used in the project from the drop-down menu.

Secondly, on Application root insert your folder name where your application resides, in my case, it is geekydocs

Thirdly, on Application URL, choose the URL/Domain that you are going to use. In my case, it is geekydocs.com

Similarly, on Application startup file, insert passenger_wsgi.py. Don't worry, it doesn't exist yet. we will talk about it later.

Then, on Application Entry Point add application

Finally, click on Create and it will create the new Python application.

Installing Dependencies

We have successfully created the Python application. now, let's install the application dependencies.

Copy the virtualenv path of the application which is highlighted at the top of the application bar
Cloning repo

In my case it is source /home3/sociobyt/virtualenv/geekydocs/3.9/bin/activate && cd /home3/sociobyt/geekydocs

Now, open up the terminal from the Cpanel tools

Opening Terminal

and paste the copied command

$ source /home3/sociobyt/virtualenv/geekydocs/3.9/bin/activate && cd /home3/sociobyt/geekydocs

This will activate the virtual environment and will change the current directory to your application's root

Then, install the application dependencies using pip

$ pip install -r requirements.txt

This will install all the dependencies of the application on our virtual environment

Configuring passenger_wsgi.py

We have successfully created the Python application, and installed its dependencies now it's time to configure passenger_wsgi.py, which will allow us to make our application public.

On the same terminal window, type the command ls then you will see, we have a new Python file called passenger_wsgi.py.

passenger_file

now, let's inspect this file and make the necessary changes to it, open the file using nano

$ nano passenger_wsgi.py

Alright, the initial setup looks like this

import imp
import os
import sys


sys.path.insert(0, os.path.dirname(__file__))

wsgi = imp.load_source('wsgi', 'passenger_wsgi.py')
application = wsgi.application

now, let's make the changes in wsgi and point it to our application wsgi.py file

import imp
import os
import sys


sys.path.insert(0, os.path.dirname(__file__))

# point to your project wsgi.py file
wsgi = imp.load_source('wsgi', 'geekydocs/wsgi.py')

application = wsgi.application

Now, let's save the changes by pressing CTRL+O and exit the editor by pressing CTRL+X

Finally, we have to restart our application to implement the changes. restart

Now, if you visit your application URL in the browser and you will see, we have successfully made our application public.

Managing Database [Skip if you are using sqlite]

If you are using a database besides sqlite, you have to configure the database server. In this case, we will be using MySQL

So, open up Cpanel tools and click on MySQL Database Wizard

Then, enter the database name

dbname

Next, create a new database user by filling up the username and password.

user

Then, give the necessary privileges to the newly created user

user

Finally, a new database along with database user is created user

Now, we have to tell Django to use this MySQL server as a database

Open up a terminal from Cpanel tools termnal

Activate the virtual environment of our Django application, copy the virtual environment path from the Python application window just like we did earlier.

$ source /home3/sociobyt/virtualenv/geekydocs/3.9/bin/activate && cd /home3/sociobyt/geekydocs

This will activate the virtual environment and will change the current directory to our application's root

To use MySQL server as a database in our Django application, we have to install a third-party library called mysqlclient

So, let's Install mysqlclient using pip

$ pip install mysqlclient

Then, open up setting.py using nano

$ nano geekydocs/settings.py

and change the database configuration

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "your_database_name",
        "HOST": "localhost",
        "USER": "database_user",
        "PASSWORD": "user_password",
        "PORT": "3306"
    }
}

Here, we are going to fill up the details that we have used while creating MySQL database earlier in the tutorial.

On NAME, enter the database name that we created earlier

On HOST, enter localhost

On USER, enter the database username that we created earler

On PASSWORD, enter the database user password

On PORT, enter 3306

Then, save the changes by pressing CTR+O and exit from the editor by pressing CTRL+X

Finally, let's migrate our database to our new MySQL server.

$ python manage.py migrate

That's it, we have successfully configured MySQL server as a database for our Django application.

Creating the separate subdomain for serving media files

You might have already figured out that we can't access our media files on the production server. You can verify that by visiting the URL of your Django application in the browser and you will see all your media files are missing.

Django by default doesn't support media file serving in the production server. So, for that, we are going to create a separate subdomain which will function as a media file server and will help us to access media files in the production.

First of all, go to the domain section of Cpanel and click on Domains

domains

Then, click on Create a new Domain

newdomain

Now, enter subdomain_name.parent_domain_name.com in this case I will enter media.geekydocs.com. In your case, It will be different. let's leave out other field defaults and click Submit

mediadomain

Alright, we successfully created the subdomain called media.geekydocs.com.

A new folder media.geekydocs.com is also created in the root directory in which we will reside our media assets.

Now, open up the terminal and let's go to the newly created folder media.geekydocs.com domains

Run the command cd in the terminal to change the directory

$ cd media.geekydocs.com

Then, create a new file called .htaccess which will allow our main domain to talk with this folder.

$ nano .htaccess
<IfModule mod_headers.c>  
    Header set Access-Control-Allow-Origin "https://www.geekydocs.com"
</IfModule>

Make sure you have changed https://www.geekydocs.com with your domain name. Now, let's save the changes by pressing CTRL+O and exit the editor by pressing CTRL+X

Alright, now we have to migrate our media files to media.geekydocs.com

On the same terminal window, let's go to our Python application root directory media_location

let's move the content of the media folder to the newly created subdomain folder media.geekydocs.com

$ mv  media/* ~/media.geekydocs.com/

Alright, now we have to point this new location as a new media folder and change the media URL of the Django application to the new subdomain. For that open settings.py

MEDIA_ROOT = "/home3/sociobyt/media.geekydocs.com/"

MEDIA_URL = "https://media.geekydocs.com/"

Enter your domain name and associated folder name and save the changes

Finally, let's restart our application to implement changes.

app_restart

That's it, now our Django application will serve the media assets from the subdomain.

Congratulations, you have successfully hosted your Django application in Cpanel, managed the static and media assets and created a new MySQL database to serve your application.

Managing application secrets and database credentials

Last but not least, we should always hide our confidential details like database credentials, app secret, API keys in environment variables. You shouldn't hard-code any sensitive information in code in a plain text.

To manage environment variables in Cpanel, go to the application tab of your Django application.

virtual

Now, let's add environment variable one by one secret_env

Now, we can access these variables in our code using the os package

import os

os.environ.get("DATABASE_USER")
os.environ.get("DATABASE_PASSWORD")

That's it, implement this to your code where you have used confidential information and credentials.

Wrapping up

Congratulations, you have successfully hosted your Django application in the production environment. That's bring us the end of this tutorial. I hope to see you again.

Thanks for sticking around.

Happy Coding!!!