Deploy Django on Your Own Server

Deploy Django applications with managed PostgreSQL, Gunicorn, and static file serving. Migrations are a one-off step you run after each deploy — see below.


Quickstart

From your project root, deploy with your preferred package manager:

npx @temps-sdk/cli up

Temps detects your requirements.txt or pyproject.toml, installs dependencies, and starts your app with Gunicorn. PostgreSQL is provisioned on first deploy.


What Temps handles automatically

FeatureHow Temps handles it
Installpip install -r requirements.txt
WSGI serverGunicorn with multiple workers
Static filesWhiteNoise middleware
HTTPSLet's Encrypt certificate, auto-renewed
PortPORT env var injected, defaults to 8000
Health checksHTTP health check on /

Database migrations are not run automatically — see Run migrations below.


Run migrations

Temps does not have a remote "run one command" CLI action yet, so migrations are run directly against the container over SSH. Find the container name, then run the migration:

bunx @temps-sdk/cli projects show -p my-django-app --json   # note the numeric "id"
bunx @temps-sdk/cli containers list -p <project-id>          # note the container_name
ssh your-server 'docker exec <container_name> python manage.py migrate'

Run this manually (or from your CI/CD pipeline right after the deploy step) every time a deploy includes a schema change. Do not add python manage.py migrate to your Dockerfile's CMD or start command — with rolling deploys, restarts, or multiple replicas, the container start command can run more than once, and concurrent migration runs against the same database can conflict or corrupt data.


Required Settings

Ensure your settings.py is production-ready:

# settings.py
import os

# Temps does not inject your domain into the container, so set this yourself
# as a project environment variable, e.g.
#   ALLOWED_HOSTS=app.example.com,www.example.com
# Defaulting to "*" would turn off Django's Host header validation.
ALLOWED_HOSTS = [h.strip() for h in os.environ.get("ALLOWED_HOSTS", "").split(",") if h.strip()]

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": os.environ.get("DB_NAME"),
        "USER": os.environ.get("DB_USER"),
        "PASSWORD": os.environ.get("DB_PASSWORD"),
        "HOST": os.environ.get("DB_HOST", "localhost"),
        "PORT": os.environ.get("DB_PORT", "5432"),
    }
}

STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

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

Environment Variables

npx @temps-sdk/cli environments vars set SECRET_KEY "your-secret-key" -e production

npx @temps-sdk/cli environments vars set DEBUG "False" -e production

npx @temps-sdk/cli environments vars set ALLOWED_HOSTS "yourdomain.com" -e production

Temps injects DATABASE_URL automatically when a managed PostgreSQL service is attached.


Managed PostgreSQL

Add a database from Project → Services → Add Service → PostgreSQL, or via CLI. Temps injects the connection details as environment variables. Run migrations yourself as described in Run migrations.


Platform behavior

These rules apply to every app deployed on Temps, regardless of framework.

The one requirement: your app must listen on the port in the PORT environment variable and bind to 0.0.0.0 — not localhost or 127.0.0.1. Temps runs your app in a container and routes traffic from the host, so an app bound to localhost only accepts connections from inside the container and will fail its health check.

Health checks

After your container starts, Temps sends HTTP GET requests to verify it is healthy before routing traffic to it.

  • Path: / (the root of your application)
  • Success: 2 consecutive responses with a 2xx or 3xx status code
  • Timeout: 300 seconds (5 minutes) for the app to become healthy
  • Retry interval: every 5 seconds

Connection errors while the app is still starting are retried without penalty. If the app returns 4xx or 5xx errors for 60 consecutive seconds, the deployment fails. Customize the check by adding a .temps.yaml to your repository root:

.temps.yaml
health:
  path: /health
  status: 200
  interval: 30
  timeout: 5
  retries: 3
Add a dedicated /health endpoint that returns a simple 200. This avoids issues where / requires authentication or returns a redirect.

Auto-injected environment variables

Temps injects these variables into every deployment automatically:

VariableValueDescription
PORTResolved portThe port your app must listen on
HOST0.0.0.0Bind address
SENTRY_DSNAuto-generatedError tracking endpoint
TEMPS_API_URLYour Temps URLPlatform API endpoint
TEMPS_API_TOKENDeployment tokenAuthentication for Temps SDKs
OTEL_EXPORTER_OTLP_ENDPOINTYour Temps OTLP URLOpenTelemetry trace collection
OTEL_SERVICE_NAMEProject nameService identifier for traces

You do not need to configure these manually. They are available in process.env (Node.js), os.environ (Python), os.Getenv (Go), and the equivalent in other languages.


Next Steps

Last updated

Was this page helpful?