iam trying to deploy my django app via cgi on strato.de . Strato only supports basic cgi so iam forced to use this method.
I already made a flask app run on strato via cgi with this tutorial ( btw great guide ). I tried to alter this and adept it to the django app to get it running on the webserver, but it looks like i am missing something.
If i call the website i run into an 500 Internal Server Error . ( I would apprieciate also some tipps how to debug this, I have no idea where to start ). Just to mention it: Everything works fine in develompent env.
Steps already done:
pip install django-cgi
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q')
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
ALLOWED_HOSTS = ['*']
I did set allowed_hosts=['*']
because i read that django wont run if its empty [] .
Q: Is it possible that i have to set the Secret_key with some bash command so the app finds it ?
Q: What exactly do i have to set allowed_hosts
to ? Something like allowed_hosts=['www.website.de']
settings.py file:
"""
Django settings for commerce project.
Generated by 'django-admin startproject' using Django 3.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
import os
from urllib.parse import urlparse
# 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/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
#SECRET_KEY = '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q'
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '6ps8j!crjgrxt34cqbqn7x&b3y%(fny8k8nh21+qa)%ws3fh!q')
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True
DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False'
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'trainer',
'tinymce',
'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 = 'denisevreden.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 = 'denisevreden.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
AUTH_USER_MODEL = 'trainer.User'
# Password validation
# https://docs.djangoproject.com/en/3.0/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/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# The absolute path to the directory where collectstatic will collect static files for deployment.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# rest of the code
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# The URL to use when referring to static files (where they will be served from)
STATIC_URL = '/static/'
# Email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.strato.de'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = *******
EMAIL_HOST_PASSWORD = *******
#csrf settings
CSRF_TRUSTED_ORIGINS = ['https://*.mydomain.com','https://*.127.0.0.1', 'https://localhost:8000']
# TinyMCE settings
TINYMCE_JS_URL = 'https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js'
TINYMCE_COMPRESSOR = False
TINYMCE_DEFAULT_CONFIG = {
"height": "320px",
"width": "960px",
"menubar": "file edit view insert format tools table help",
"plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code "
"fullscreen insertdatetime table paste code help wordcount spellchecker",
"toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft "
"aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor "
"backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | "
"fullscreen preview save print | insertfile image pageembed template link anchor codesample | "
"a11ycheck ltr rtl | showcomments addcomment code",
"custom_undo_redo_levels": 10,
}
manage.py file:
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import dependencies
import os, sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'denisevreden.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
** cgi_handler.py:**
#!/usr/local/python/3.10.4/bin/python
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
happy.cgi file :
#!/usr/bin/python3
import os
import sys
#!/usr/bin/env python
import os
import sys
# Add the path to the Django project to the system path
sys.path.append('/mnt/web315/a3/18/512337018/htdocs/.cgi-bin/Happy-dv')
# Set the environment variable to tell Django where the settings module is
os.environ['DJANGO_SETTINGS_MODULE'] = 'Happy-dv.settings'
# Import the CGIHandler class
from wsgiref.handlers import CGIHandler
# Run the application using the CGIHandler
CGIHandler().run(application)
try:
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
except Exception as err:
print("Content-Typ: text/html\n\n")
print(err)
dependencies.py file:
#!/usr/bin/python3
import os
import sys
#!/usr/bin/env python
import os
import sys
# Add the path to the Django project to the system path
sys.path.append('/mnt/web315/a3/18/512337018/htdocs/.cgi-bin/Happy-dv')
# Set the environment variable to tell Django where the settings module is
os.environ['DJANGO_SETTINGS_MODULE'] = 'Happy-dv.settings'
# Import the CGIHandler class
from wsgiref.handlers import CGIHandler
# Run the application using the CGIHandler
CGIHandler().run(application)
try:
import wsgiref.handlers
from denisevreden.wsgi import application
wsgiref.handlers.CGIHandler().run(application)
except Exception as err:
print("Content-Typ: text/html\n\n")
print(err)
THanks
There is a CGI script available for Django.
This however does have some serious drawbacks.
Because of the way CGI works; it spawns a new process every time a request is made.
This basically means it will start up django on every request.
It might also have some serious security implications; as listed here.
CGI software has the potential to create some enormous security holes on your system. If they are carelessly programmed, they allow evildoers out there on the Internet to enter Unix commands into a form and have them executed on your web server. This article covers the basics of making your CGI software secure.
That aside; the script is publicly available in the following github respository: https://github.com/chibiegg/django-cgi/blob/master/django-python3.cgi
The repo is rather old; so I cannot promise it will work out of the box.
#!/home/user/.pyenv/versions/envname/bin/python
# encoding: utf-8
"""
django-.cgi
A simple cgi script which uses the django WSGI to serve requests.
Code copy/pasted from PEP-0333 and then tweaked to serve django.
http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side
This script assumes django is on your sys.path, and that your site code is at
/djangoproject/src. Copy this script into your cgi-bin directory (or do
whatever you need to to make a cgi script executable on your system), and then
update the paths at the bottom of this file to suit your site.
This is probably the slowest way to serve django pages, as the python
interpreter, the django code-base and your site code has to be loaded every
time a request is served. FCGI and mod_python solve this problem, use them if
you can.
In order to speed things up it may be worth experimenting with running
uncompressed zips on the sys.path for django and the site code, as this can be
(theorectically) faster. See PEP-0273 (specifically Benchmarks).
http://www.python.org/dev/peps/pep-0273/
Make sure all python files are compiled in your code base. See
http://docs.python.org/lib/module-compileall.html
"""
import os, sys
# Change this to the directory above your site code.
# sys.path.append("/home/user/local/lib/python3.4/site-packages")
# sys.path.append("/djangoproject/src")
def run_with_cgi(application):
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin.buffer
environ['wsgi.errors'] = sys.stderr.buffer
environ['wsgi.version'] = (1,0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS','off') in ('on','1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
def write(data):
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent:
# Before the first output, send the stored headers
status, response_headers = headers_sent[:] = headers_set
sys.stdout.buffer.write(('Status: %s\r\n' % status).encode("ascii"))
for header in response_headers:
sys.stdout.buffer.write(('%s: %s\r\n' % header).encode("ascii"))
sys.stdout.buffer.write(('\r\n').encode("ascii"))
sys.stdout.buffer.write(data)
sys.stdout.buffer.flush()
def start_response(status,response_headers,exc_info=None):
if exc_info:
try:
if headers_sent:
# Re-raise original exception if headers sent
raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
finally:
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status,response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
result.close()
# Change to the name of your settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'application.settings'
from django.core.wsgi import get_wsgi_application
run_with_cgi(get_wsgi_application())