Maisie Marks

‎ Personal Website

Python Django SQL
(project github)
I deployed my full-stack personal website to showcase hobbies and projects, fully containerised and self-hosted on a Linux machine using Python with Django, Gunicorn for the WSGI server, NGINX for the reverse proxy, PostgreSQL for the database and Cloudflare for DNS and security. Using automation, Docker and Git alongside local and development environments to efficiently test and deploy updates in real-time.

The website was originally pure HTML and CSS, but after using Django in a project at uni, I decided I would convert it to Django for more ease of use. Having Django as opposed to using modules like flask makes it a lot easier to manage a database. Each "Post" model has one-to-many relationships with "Tags" "Images" and "Videos" models. As well as the personal "Me" model has a one-to-many relationship with "Abilities", showcasing my coursework and certificate achievements.

Development Log

Pre-requisites Before Deployment

Purchasing a domain

You will first need to purchase a domain to host on, I chose to use Porkbun for mine as as its cheap and easy to setup and has WHOIS privacy.

I'm using Cloudflare to route my traffic through, this means that I don't need to expose ports on my network and use port forwarding/ static ips to host from my home network.

Another benefit of Cloudflare is their zero-trust settings, and this is how I use them to ensure my website is extra privacy-protected while deploying: This ensures that during setup, the website still can be reached by your domain.com, except it is password protected, incase you run into issues during setup and need to put it in DEBUG mode which can expose vulnerable info.

Hardware and OS setup

I opted for hosting locally as in future I want to be able to access my locally hosted services from my website. I'm using a spare Dell OptiPlex 3050 to deploy on using ethernet for the most reliable internet connection. For the OS, I opted for using Ubuntu for its stability and ease of use. I mounted the Ubuntu 24.04.2 LTS iso on a USB stick using Ventoy and set it up with my JetKVM to remote into from my main pc.

Useful Initial Settings

Enable autosign in (in settings)

Settings > System > Users
unlock the panel with your password
toggle the "Automatic Login"

Disabling screen timeout (in settings)

Power>Screen Blank>Never

Installing Docker

Pre-requisite if not using gnome
     
sudo apt install gnome-terminal

Install Docker's apt repository

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Install the latest docker packages

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Download the latest DEB package from the website

Install the package using apt (need to be in the directory of the install .deb file)

sudo apt-get update
sudo apt-get install ./docker-desktop-amd64.deb

Install Docker Compose

sudo apt install docker-compose

Start Docker

systemctl --user start docker-desktop

Build the image

docker-compose -f docker-compose.prod.yml up --build


Pulling the code

Install git

sudo apt install git-all

Make a personal access token (PAT) to sign in with Github with read only permissions of contents
(this allowed me to pull the code pre-publishing) Git clone the repository (using the PAT as the password when prompted)

git clone https://github.com/loopymeow/website-portfolio.git


Modifying the code

Generate a secure key

python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'


Building the image

Configure the .env.prod settings:

#django settings
DEBUG=False
SECRET_KEY= <--(put generated key here !!)
ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0 <--(add yourdomain.your tld)
CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1 <--(add https://yourdomain)
DATABASE_URL=postgres://postgres:password@db:5432/postgres

#database settings
DB_ENGINE = django.db.backends.postgresql_psycopg2
DB_NAME = postgres
DB_USERNAME = postgres
DB_PASSWORD = password
DATABASE_HOST = db
DATABASE_PORT = 5432

Connecting the webserver to the internet

  1. Download Cloudflared (Cloudflare daemon) and install it (for my pc using .deb amd64 version)
  2. Log into Cloudflare and navigate to the Zero Trust panel
  3. Navigate to Networks -> Tunnels -> Create a Tunnel
  4. Create the tunnel, giving it a custom name, and you will be given its token

Run this to dockerise the tunnel with its given token

docker run cloudflare/cloudflared:latest tunnel —no-autoupdate -run —token (token)

You can close and reopen the tunnel using this for a shorter command that ensures it stays connected even after a computer restart.

docker run -d —name cloudflared —restart unless-stopped cloudflare/cloudflared:latest tunnel run (tunnelname)



^ If all containers are showing green and no errors, then the setup is complete. If anything is not working, I recommend altering the .env.prod to change debug to true to help spot any issues.

(images of my lovely helpful website system administrator below) :>

Media: