Deploy Django with AZIN

All guides
Django
Deploy Guides·1 min read

Deploy Django with AZIN

deploydjangopython

Django deployment has always meant configuring Gunicorn, Nginx, static files, database connections, and a dozen environment variables. AZIN detects your Django project, sets up the WSGI server, runs collectstatic, provisions PostgreSQL, and deploys to your own GCP account. No Nginx. No Procfile. Push code, it's live.

#How AZIN detects Django

AZIN uses Railpack to auto-detect your project. When it finds manage.py and a Python dependency file (requirements.txt, pyproject.toml, or Pipfile), it identifies a Django project and configures the build automatically.

What Railpack sets up for you:

  • Python version from .python-version or runtime.txt (defaults to 3.13)
  • Dependency installation via pip, Poetry, PDM, or uv based on your lockfile
  • Gunicorn as the WSGI server with a sensible worker configuration
  • collectstatic to gather static assets before the app starts
  • Database migrations via python manage.py migrate on each deploy

The default start command Railpack generates:

python manage.py migrate && gunicorn myproject.wsgi

No Procfile needed. No Dockerfile needed. If you want either, AZIN supports both — but for most Django apps, Railpack auto-detection handles everything.

#Deployment config

Connect your GitHub repo, and AZIN deploys on every push. For a Django app with PostgreSQL, here's the full azin.yaml:

name: my-django-app
cloud: gcp
region: europe-west4
services:
  web:
    build:
      type: railpack
    env:
      DJANGO_SETTINGS_MODULE: myproject.settings.production
      ALLOWED_HOSTS: ".azin.run,.yourdomain.com"
      DEBUG: "false"
    scaling:
      min: 1
      max: 10
      target_cpu: 70
  db:
    type: postgres
    plan: production
  cache:
    type: redis

AZIN injects DATABASE_URL and REDIS_URL into your web service automatically. No manual connection string configuration.

#Django settings for production

Your settings.py needs a few changes for production. Use dj-database-url to parse the injected DATABASE_URL, and pull secrets from environment variables:

# settings/production.py
import os
import dj_database_url
 
SECRET_KEY = os.environ["SECRET_KEY"]
DEBUG = False
ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS", "").split(",")
 
DATABASES = {
    "default": dj_database_url.config(
        default=os.environ.get("DATABASE_URL"),
        conn_max_age=600,
    )
}
 
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
 
# WhiteNoise for static file serving — no Nginx required
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    # ... remaining middleware
]
 
STORAGES = {
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

Add gunicorn, dj-database-url, and whitenoise to your requirements.txt:

Django>=6.0,<6.1
gunicorn>=23.0
dj-database-url>=2.3
whitenoise>=6.8
psycopg[binary]>=3.2

That's the entire production configuration. No Nginx config files, no systemd units, no reverse proxy setup.

#Adding Celery workers

Django apps commonly need background task processing. Add a Celery worker as a separate service in azin.yaml:

name: my-django-app
cloud: gcp
region: europe-west4
services:
  web:
    build:
      type: railpack
    env:
      DJANGO_SETTINGS_MODULE: myproject.settings.production
  worker:
    build:
      type: railpack
    start: celery -A myproject worker --loglevel=info
    env:
      DJANGO_SETTINGS_MODULE: myproject.settings.production
  beat:
    build:
      type: railpack
    start: celery -A myproject beat --loglevel=info
    env:
      DJANGO_SETTINGS_MODULE: myproject.settings.production
  db:
    type: postgres
    plan: production
  cache:
    type: redis

All three services (web, worker, beat) share the same codebase, the same DATABASE_URL, and the same REDIS_URL. AZIN provisions Redis alongside Postgres and injects both connection strings.

#Environment variables and secrets

Django requires several environment variables in production. Set them through the AZIN dashboard. A CLI is on our roadmap — the commands below show the planned interface:

azin env set SECRET_KEY "your-production-secret-key"
azin env set ALLOWED_HOSTS ".yourdomain.com"
azin env set DEBUG "false"
azin env set DJANGO_SETTINGS_MODULE "myproject.settings.production"

DATABASE_URL and REDIS_URL are injected automatically when you add database and cache services. Never hardcode these.

For sensitive values like API keys and payment credentials, AZIN encrypts environment variables at rest and injects them at runtime. They never appear in build logs or container images.

#Why AZIN for Django

Deploy to your cloud. Your Django app and Postgres database run in your own GCP account, with AWS and Azure on our roadmap. You own the infrastructure, the data, and the billing relationship with your cloud provider.

No WSGI server configuration. Railpack detects Django and configures Gunicorn with appropriate worker counts based on available CPU. The formula (2 * CPU) + 1 is applied automatically.

Managed PostgreSQL. AZIN provisions Cloud SQL in your GCP account. Automated backups, connection pooling, and scaling included. The connection string is injected as DATABASE_URL.

Scale-to-zero staging. Deploy staging environments on lttle.cloud (in early access). When no traffic hits your staging Django app, it scales to zero. No idle costs for environments you only use during development.

Django 6.0 ready. As of February 2026, Django 6.0.2 is the latest stable release. Railpack supports Python 3.8 through 3.13, covering every Django version in active support.

Deploy Guides

Host PostgreSQL with AZIN

Managed Cloud SQL in your own GCP account. Automated backups, encryption at rest, and your data never leaves your VPC.

#Frequently asked questions

Deploy on private infrastructure

Managed AI environments with built-in isolation. Zero DevOps required.