'DisallowedHost at /admin -- Django, Gunicorn, NGINX -- Error first showed when changed to HTTPS only instead of just HTTP
This is a screenshot of the error when you access my domain, insa-analytics.com/admin:

Here is a text dump of that image for those who cannot access the image:
DisallowedHost at /admin
Invalid HTTP_HOST header: 'insa-analytics.com'. You may need to add 'insa-analytics.com' to ALLOWED_HOSTS.
Request Method: GET
Request URL: http://insa-analytics.com/admin
Django Version: 4.0.2
Exception Type: DisallowedHost
Exception Value:
Invalid HTTP_HOST header: 'insa-analytics.com'. You may need to add 'insa-analytics.com' to ALLOWED_HOSTS.
Exception Location: /usr/local/lib/python3.8/dist-packages/django/http/request.py, line 135, in get_host
Python Executable: /usr/bin/python3
Python Version: 3.8.10
Python Path:
['/home/django/django_project',
'/usr/bin',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/usr/local/lib/python3.8/dist-packages',
'/usr/lib/python3/dist-packages']
Server time: Mon, 18 Apr 2022 22:33:43 +0000
The /admin is the administrator control panel for the Django service. Previously, this webserver was working perfectly via HTTP (no SSL, 80 instead of 443). When I used certbot with letsencrypt to generate and configure an SSL certificate -- this issue came into play.
Note that I redirect all HTTP connections to HTTPS. My webservice will be only accessible over 443.
settings.py:
"""
Django settings for django_project project.
Generated by 'django-admin startproject' using Django 2.2.12.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
import netifaces
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = OMITTED_FOR_STACK_OVERFLOW_QUESTION
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
# Find out what the IP addresses are at run time
# This is necessary because otherwise Gunicorn will reject the connections
def ip_addresses():
ip_list = []
for interface in netifaces.interfaces():
addrs = netifaces.ifaddresses(interface)
for x in (netifaces.AF_INET, netifaces.AF_INET6):
if x in addrs:
ip_list.append(addrs[x][0]['addr'])
return ip_list
ALLOWED_HOSTS = ip_addresses()
ALLOWED_HOSTS += ['insa-analytics.com']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'django_project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'django_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'django',
'USER': 'django',
'PASSWORD': 'e1ceb12e126563cc2b5fa8a91f318db9',
'HOST': 'localhost',
'PORT': '',
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
nginx server block cfg:
upstream app_server {
server unix:/home/django/gunicorn.socket fail_timeout=0;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 4G;
server_name _;
keepalive_timeout 5;
# Your Django project's media files - amend as required
location /media {
alias /home/django/django_project/django_project/media;
}
# your Django project's static files - amend as required
location /static {
alias /home/django/django_project/django_project/static;
}
# Proxy the static assests for the Django Admin panel
location /static/admin {
alias /usr/lib/python3/dist-packages/django/contrib/admin/static/admin/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://app_server;
}
}
server {
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 4G;
server_name insa-analytics.com; # managed by Certbot
keepalive_timeout 5;
# Your Django project's media files - amend as required
location /media {
alias /home/django/django_project/django_project/media;
}
# your Django project's static files - amend as required
location /static {
alias /home/django/django_project/django_project/static;
}
# Proxy the static assests for the Django Admin panel
location /static/admin {
alias /usr/lib/python3/dist-packages/django/contrib/admin/static/admin/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://app_server;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/insa-analytics.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/insa-analytics.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
server_name www.insa-analytics.com;
return 301 $scheme://insa-analytics.com$request_uri;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/insa-analytics.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/insa-analytics.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = insa-analytics.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name insa-analytics.com;
return 404; # managed by Certbot
}
server {
if ($host = www.insa-analytics.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name www.insa-analytics.com;
listen 80;
return 404; # managed by Certbot
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
