NewSchokr 13 is here. A whole new UI, seven locations, snapshots and more. Read more →

How to deploy a Django app (gunicorn, ALLOWED_HOSTS, static files)

Run Django in production on Schokr: gunicorn, ALLOWED_HOSTS, DEBUG off, collectstatic with WhiteNoise, migrations and SQLite.

Updated · 1 min read

To run Django on Schokr, serve it with gunicorn on 0.0.0.0 and your allocated port, set ALLOWED_HOSTS and DEBUG = False, collect static files, and run migrations before starting.

1. requirements.txt

Django==5.1.2
gunicorn==23.0.0
whitenoise==6.7.0
python-dotenv==1.0.1

2. Production settings

In settings.py:

import os
from pathlib import Path
from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent.parent
load_dotenv(BASE_DIR / ".env")

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

Add WhiteNoise right after SecurityMiddleware so Django can serve its own static files:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    # ...the rest
]

Create .env in the project root (next to manage.py):

DJANGO_SECRET_KEY=generate-a-long-random-string
DJANGO_ALLOWED_HOSTS=your-server-address,yourdomain.com

ALLOWED_HOSTS must contain the host name people type in the browser, without the port. If it does not, Django returns "Bad Request (400)".

3. Database

Schokr has no built-in database server. Django's default SQLite database works well for small and medium sites on a single server; see SQLite in production. For PostgreSQL, use an external provider and set DATABASES from an environment variable.

4. Startup command

Run migrations and collect static files, then start gunicorn:

python manage.py migrate --noinput && python manage.py collectstatic --noinput && gunicorn myproject.wsgi:application --bind 0.0.0.0:25571 --workers 2

Replace myproject with the folder that contains wsgi.py, and 25571 with your port. If your template only runs a Python file, you can create a small run.py that calls these steps with subprocess, or run migrations once and start gunicorn from code.

5. Deploy

  1. Create a Python server in the console. Give it 512 MB to 1 GB.
  2. Upload your project (without your venv, __pycache__ or staticfiles) with the file manager.
  3. Set the startup command in your server's Startup settings and start the server.
  4. Open http://<server-address>:<port>.

Admin user

Create a superuser locally against the same SQLite file before uploading it, or temporarily add a data migration. The server console passes input to your running app, so interactive createsuperuser prompts do not work there.

Troubleshooting

ProblemFix
Bad Request (400)Add the host to ALLOWED_HOSTS.
CSS missingRun collectstatic and check WhiteNoise is in MIDDLEWARE.
CSRF verification failed behind HTTPS proxyAdd your https:// origin to CSRF_TRUSTED_ORIGINS.
ModuleNotFoundError: myprojectWrong module path in the gunicorn command. See module not found.