Railway

Deploy Django REST | API with Postgres and a Generated Secret Key

Django 6 and DRF on Railway, with a signing key generated per deployment

Deploy Django REST | API with Postgres and a Generated Secret Key

/var/lib/postgresql/data

Deploy and Host a Django REST API on Railway

Django 6 and Django REST Framework on Postgres, with a signing key generated per deployment.

About Hosting Django on Railway

The Django REST template most people deploy was last touched in September 2023 - Django 4.2, DRF 3.14, psycopg2 - and none of its deployments report healthy. But the stale versions are not the worst part.

Its SECRET_KEY is a literal, committed into the template. Every project deployed from it shares the same Django signing key, and that template is public. Anyone who reads it can forge session cookies and password-reset tokens against every site created from it.

Here SECRET_KEY is generated per deployment. The settings module reads it with os.environ["SECRET_KEY"] rather than os.environ.get(..., "fallback"), so a missing key stops the app at startup instead of quietly falling back to a shared default - which is how a template ends up shipping one key to everybody in the first place.

Common Use Cases

  • A JSON API with a relational model, an admin UI and migrations from day one
  • The backend for a front end you host separately
  • An internal tool where the Django admin is most of the product

Dependencies for Django Hosting

  • Postgres, included, on a persistent volume
  • Nothing else. Without DATABASE_URL it falls back to SQLite, so local development needs no database.

Deployment Dependencies

Implementation Details

MethodPathDoes
GET/api/health/Runs SELECT 1; 503 when Postgres is unreachable
GET/api/notes/Paginated list
POST/api/notes/Creates a note - requires authentication
-/admin/Django admin

Create the first user after deploying, from the service shell: python manage.py createsuperuser.

Four settings exist because of how Railway runs the app, and each one costs an afternoon to rediscover:

  • SECURE_PROXY_SSL_HEADER. TLS terminates at the platform proxy. Without this Django believes every request is plain HTTP and builds http:// redirects that break the admin login.
  • ALLOWED_HOSTS includes healthcheck.railway.app. The health checker reaches the container over the internal network, so its requests carry a different Host header. Without that entry Django answers the health check with 400 and the deployment is marked failed while the app is running perfectly well.
  • collectstatic runs in the build, not in pre-deploy. The pre-deploy step runs in a separate throwaway container; files it writes never reach the running app, and Django then warns "No directory at: /app/staticfiles/" and returns 500 for the admin.
  • migrate runs in pre-deploy, not in the build. The build has no database to connect to.

Why Deploy Django on Railway?

A database, a domain and TLS from one deploy, migrations applied before each release takes traffic, and a health check that fails when the database is gone rather than when Django is merely unhappy about a header.


Template Content

More templates in this category

View Template
open-excalidraw
Self-hostable collaborative drawing built on Excalidraw

Prateek Mohanty
1
View Template
caring-vibrancy
Deploy and Host caring-vibrancy with Railway

5
View Template
Flask WebSocket Chat
Single file, realtime multi-user websocket chat using flask-socketio

Clement Ochieng
3