Deploying a Django Application!
Over the course of this post, I will be deploying a Django Web Application to a private Ubuntu VPS instance through Hostinger.
Patrik Gammon
4/16/20242 min read
You are probably reading this article on my personal website, Patrikgammon.com. I have hosted dozens of websites and web servers in my days. When I first began working on internet content, I used the traditional LAMP stack (Linux, Apache, MySQL, PHP). I hosted a few PHP bulletin boards and scoreboards for Flash browser games.
Now that flash games are gone, I too have had to move on. These days I prefer to launch either RESTful microservices in Go, or a more monolithic solution like Django. For this web application, I will be deploying Django on Ubuntu 22.04 using Gunicorn for WSGI and NGINX as a reverse proxy. NGINX will also serve the static media content for the django app.
Today, 4/16/24 I procured my server and the domain name patrikg.com. I have done my first ssh into the server and updated the software using:
sudo apt update (always takes a long time)
sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx (I think that's all we need)
I did some quick test work in postgres to make sure I could create a db/user/table etc. Works as expected. I set up a working directory call "patrikgdotnet"
mkdir ~/patrikgdotnet
cd ~/patrikgdotnet
python3 -m venv patrikgenv
source patrikgenv/bin/activate
This creates a virtual environment in python where my dependencies can be properly managed independently. This allows me to pull the code from a repository like github and know that the required dependencies will be included as long as the environment is built from the same requirements.txt file.
pip install django gunicorn psycopg2-binary
pip freeze > requirements.txt
Now we can finally initialize our Django Project. I will use a demo project for now and build it out once we're deployed.
django-admin startproject patrikgwebsite ~/patrikgwebsite
By default, Django runs on a SQLite DB. SQLite is awesome for rapid development, but postgresql offers better features and speed. We will need to update our newly created "settings.py" to reflect this design choice.
This tells Django to try connection to our PostgresDB "patrikgdotcom". Instead of making a new Sqlite.db file.
python3 manage.py makemigrations
python3 manage.py migrate
Typically you would create a Django Superuser at this point, but I will be using a custom auth/profile module and don't want to migrate the db back and forth.
Next we will configure NGINX to serve over HTTPS for security. We do this using the certbot tool.
Now that our domain name points to the server IP, and the server IP has a signed TLS certificate associated with it, our website should be visible using HTTPS in a browser. The domain is "www.patrikg.com" take a look and you should see a little lock symbol from your browser indicating that the server session is secure.
Now at this point we're just serving raw HTML from Nginx. We're not returning any data from our Django App. In order to do that, we will need to plug our Django app into Nginx with a WSGI server using Gunicorn. We will discuss that next time!


DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'patrikgdotcom',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}