How to Django, Certbot — HTTPS Subdomains

This article will go through how I got subdomains to work on Django 3 with Certbot for https. It was a little finicky to get working, since I couldn’t find much info on some specific errors I was running into. Maybe I’m just not a high level search engine ninja, but I figured it out myself. My server was using nginx, but I think it shouldn’t matter if you use apache or something else. There are 3 components to get subdomains to work on Django with https: modifying domain records, using subdomains package for Django, and adding the subdomain to your certificate with certbot .

A/AAAA + CNAME Record

A/AAAA
Hostname: subdomain
IP Address: your_server_ip
CNAME
Hostname: *.subdomain
Aliases to: subdomain.example.com

pip install subdomains

pip install subdomains

https://github.com/abe312/django-subdomains. As of writing this, subdomains is working with Django 3.

Setup: subdomains require you to configure the app’s settings, the urlpatterns, and database object values correctly.

# subdomains settings: project/project/settings.py
INSTALLED_APPS = [
...
"django.contrib.sites",
"subdomains",
]
# subdomains line needs to go before CommonMiddleware
MIDDLEWARE = [
...
"subdomains.middleware.SubdomainURLRoutingMiddleware",
'django.middleware.common.CommonMiddleware',
...
]
# values are app's path
ROOT_URLCONF = "project.urls"
SUBDOMAIN_URLCONFS = {
None: "project.urls",
"subdomain": "subdomain_app.urls"
}
SITE_ID = 1

Next, we need to configure the route in your urls.py of the project. Take note that there is no slash for the subdomain path.

# urlpatterns: project/project/urls.py
from django.urls import path, include
urlpatterns = [
...
path(r"subdomain", include("subdomain_app.urls")),
]

Lastly, from the setup in subdomains docs, we need to set the Site object in our database.

> python manage.py makemigrations
> python manage.py migrate
> python manage.py shell
from django.contrib.sites.models import Site
one = Site.objects.all()[0]
one.domain = 'example.com'
one.name = 'example'
one.save()

Subdomains Development and Production

# settings.py
prj_env = "dev" # Put your env var with your favorite method
if prj_env == "dev":
DEBUG = True
ALLOWED_HOSTS = ["localhost", "subdomain.localhost"]
else:
DEBUG = False
ALLOWED_HOSTS = ["example.com", "www.example.com", "subdomain.example.com", "www.subdomain.example.com"]

This should be all we need for Django to point a subdomain request to the correct view. At this point, development on localhost should be working. Follow the next steps to get it working on production.

Certbot

# on prod server
> certbot -d domain1,domain2,new_subdomain --expand
# restart nginx, i'm using ubuntu here
> sudo service nginx restart

Subdomains should be working now. I’d like to hear in the comments if there is any better way to handle subdomains in Django.

Software Engineer living in Tokyo | Linux | Cats | https://github.com/kai-dg | https://haruspace.dev | https://ko-fi.com/harukai

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store