Deploy Django with Postgres

This guide deploys a Django app to Naijacloud with a managed Postgres database. At the end you’ll have the app and the Django admin running over HTTPS at your own naijacloud.app address, with migrations applied every time the app starts and every push to your branch deploying automatically. The stack is Django 6, Gunicorn, WhiteNoise and Postgres 18, deployed from a GitHub repository.

15 minBeginnerLast verified 2026-10-11djangopostgres
What you'll have at the end

A Django app and the Django admin on your own naijacloud.app address, reading and writing to managed Postgres. Open /admin to sign in.

Deploy this templateDjango + Postgres API template

Before you start

  • A Django project in a GitHub repository. Starting fresh? Run django-admin startproject mysite . and push it.
  • Python 3.12 or newer on your machine. Naijacloud builds Python apps on Python 3.12.
  • A Naijacloud account. The free tier covers this guide: one web service and one database.

Add the production packages

Django’s development server isn’t built for real traffic. Add Gunicorn to serve the app, WhiteNoise to serve static files, and the two packages that let Django reach Postgres through a single DATABASE_URL.

Terminal
$ pip install django gunicorn whitenoise dj-database-url "psycopg[binary]"
$ pip freeze > requirements.txt

Naijacloud finds requirements.txt, recognises Django in it and installs it with pip install -r requirements.txt. Commit the file with the next step.

Read settings from the environment

Open mysite/settings.py. Replace the hard-coded secret key, debug flag, hosts and database with values read from the environment, and give static files a folder WhiteNoise can serve.

mysite/settings.py
import os
import dj_database_url
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "False") == "True"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost").split(",")
# Naijacloud terminates HTTPS in front of your app
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
DATABASES = {"default": dj_database_url.config(conn_max_age=600)}
STATIC_ROOT = BASE_DIR / "staticfiles"
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"},
}

From now on manage.py needs these variables too, so set them in your shell before running it locally: export DJANGO_SECRET_KEY=dev DJANGO_DEBUG=True DATABASE_URL=sqlite:///db.sqlite3.

Create the admin user on start

You’ll never need to connect to the database from your laptop. Instead, a short management command creates your admin user from two variables the first time the app starts, and does nothing after that.

Terminal
$ python manage.py startapp core
$ mkdir -p core/management/commands

Add "core" to INSTALLED_APPS in mysite/settings.py, then create the command:

core/management/commands/ensure_admin.py
import os
from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "Create the admin user from environment variables, once."
def handle(self, *args, **options):
User = get_user_model()
username = os.environ["DJANGO_ADMIN_USER"]
if User.objects.filter(username=username).exists():
return
User.objects.create_superuser(
username=username,
email="",
password=os.environ["DJANGO_ADMIN_PASSWORD"],
)
self.stdout.write(f"Created admin user {username}")
Terminal
$ git add .
$ git commit -m "Prepare for Naijacloud"
$ git push

Create the database

In the dashboard, open your project and choose New service → Database. Name it (for example mysite-db), pick Postgres, leave the connection details blank so they’re generated, choose the Free size and click Create database.

The next screen, mysite-db is ready., shows the connection details once. Click Reveal secrets and copy the Internal URL. Your app uses it to reach the database over the private network.

Create the web service

Back in the project, choose New service → Web service. Name it mysite; that name becomes your address, mysite.naijacloud.app. Under Source, choose GitHub and pick your repository and branch. Naijacloud detects Django and fills in the commands. Change them to these:

Build commandpip install -r requirements.txt
Start commandpython manage.py collectstatic --noinput && python manage.py migrate && python manage.py ensure_admin && gunicorn mysite.wsgi --bind 0.0.0.0:$PORT

Everything runs in the start command because your variables are set when the app starts. The command collects static files, applies migrations and creates the admin user before Gunicorn begins serving, so the database is ready by the time the app answers. Naijacloud sets PORT for you.

Set the variables

On the same screen, under Environment variables, click Paste .env and paste these five lines with your own values, then Add variables. Generate the secret key on your machine first:

Terminal
$ python -c "import secrets; print(secrets.token_urlsafe(50))"
k7Qv2mX0f9Rz…
DATABASE_URLThe Internal URL you copied from the database
DJANGO_SECRET_KEYThe value you just generated
DJANGO_ALLOWED_HOSTS.naijacloud.app
DJANGO_ADMIN_USERThe username you’ll sign in with
DJANGO_ADMIN_PASSWORDA long password. It’s only read the first time the app starts

Deploy and sign in

Leave Region and Instance type as they are. Free is enough for this guide. Free apps may sleep when nobody visits for a while and wake on the next request; paid apps never sleep. Click Create web service, then Open mysite. The Deploys tab streams the build log. When the deploy goes live, the start command’s output appears in Logs under Runtime:

Runtime log · mysite
130 static files copied to '/app/staticfiles', 390 post-processed.
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
…
Created admin user ada
[INFO] Starting gunicorn 26.2.0
[INFO] Listening at: http://0.0.0.0:8000

Open https://mysite.naijacloud.app/admin and sign in with the username and password you set. From now on every push to your branch deploys, and the start command migrates the database first.

Whatever you build it with, it ships here.

Deploy your app for free

Free tier forever · No card