Skip to main content

Application settings

Before you can deploy your app, you need to update your settings.py file so your app can run properly in both development and production environments. If you don’t already have a preferred approach to handle your settings, you can use django-environ. You can install django-environ with your package manager.
pip install django-environ
django-environ reads values from .env in your project’s base directory. At a minimum, .env needs to include the following variables:
  • DEBUG
  • SECRET_KEY
  • ALLOWED_HOSTS
  • CSRF_TRUSTED_ORIGINS
  • DATABASE_URL
These are the environment variables that typically vary between development and production. You can also add any other project-specific environment variables. This .env will only contain your development values.
# .env
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
SECRET_KEY=<your-secret-key-here>
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
DATABASE_URL=sqlite:///db.sqlite3
After you’ve created the .env file, you need to update your settings.py file so django-environ can read .env and set the appropriate settings. DEBUG should default to False, so your production environment never starts in debug mode.
# settings.py
import os 
import environ 

from pathlib import Path

env = environ.Env(DEBUG=(bool, False)) 

BASE_DIR = Path(__file__).resolve().parent.parent

environ.Env.read_env(os.path.join(BASE_DIR, '.env')) 
For each setting, you can use the env object to retrieve the value. For values that accept a list, env.list will convert comma-separated values to a Python list. If those values don’t exist, you should default to an empty list, so you have no allowed hosts or CSRF trusted origins.
SECRET_KEY = env('SECRET_KEY') 

DEBUG = env('DEBUG') 

ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[]) 
CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS', default=[]) 
For the database, use env.db() on the default database; this loads the DATABASE_URL value defined in your environment variables.
# settings.py
DATABASES = {
    'default': { 
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
    'default': env.db(), 
}

Add a hosted database

The filesystem used for your app will be recreated on each deploy, so an SQLite database isn’t suitable for production. Instead, you can use a hosted database on Sevalla for your app. Create a database in Sevalla and select either Postgres, MySQL, or MariaDB. You also need to install a database driver if you haven’t already done so. For example, with Postgres, you can use psycopg2-binary.
pip install psycopg2-binary

Application server and static files

Django’s built-in development server is not intended for production use, so you should run your application with Gunicorn instead. Because the development server also handles static files by default, you’ll need to use Whitenoise to serve static assets in production. Both Gunicorn and Whitenoise must be installed via your package manager as part of your deployment setup.
pip install gunicorn whitenoise
To use Whitenoise, you only need to add its middleware in settings.py. This middleware should be placed after the SecurityMiddleware.
# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', 
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
For static files to work properly, you need to define the STATIC_ROOT variable in settings.py.
STATIC_ROOT = BASE_DIR / 'staticfiles'

Nixpacks

By default, Sevalla builds your application using Nixpacks. Nixpacks can detect that you have a Python app, but you need to specify any extra commands needed to build your app. You also need a start command to tell Nixpacks how to start your app. You can define both commands in a nixpacks.toml file in your base directory. For the build command, you need to run collectstatic. For the start command, you need to run both the migrate and gunicorn command. After the gunicorn command, specify the name of your Django project followed by .wsgi. The $PORT variable can be used to start your app on the port defined in your Sevalla application.
[phases.build] 
cmds = ["python manage.py collectstatic --noinput"]

[start] 
cmd = "python manage.py migrate && gunicorn example.wsgi -b 0.0.0.0:$PORT"
Finally, generate a requirements.txt file so your dependencies install during deployment.
pip freeze > requirements.txt

Dockerfile

To build your application from a Dockerfile, you need a Dockerfile that ends with your application being started by Gunicorn or any other WSGI server. The following is a sample Dockerfile that sets up a Python environment, installs your dependencies, collects static files, and then starts a Gunicorn server.
FROM python:latest  

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1 
 
RUN mkdir /app
WORKDIR /app
 
RUN pip install --upgrade pip 
COPY requirements.txt  .
RUN pip install --no-cache-dir -r requirements.txt
 
COPY . .

ARG SECRET_KEY
ARG DATABASE_URL

RUN python3 manage.py collectstatic --no-input

CMD ["gunicorn", "example.wsgi"]
Django management commands can’t run without a secret key and database set, so the ARG directive is used to make the associated environment variables available to the build process. These environment variables should be set as available at both buildtime and runtime before deploying your app for the first time. The command to start with Gunicorn needs to reference the name of your project’s WSGI file. The rest of the Dockerfile can be customized according to your project’s specific needs.

Migrations

Migrations need to happen outside the Dockerfile because there won’t be a reference to your actual database in the Dockerfile. Additionally, your migrations must run after your image has been built but before the container is started. You can create a job to run the migrate command before the container is started. To do this, after you add your application, go to Processes > Create job > Job. For the start command, add python manage.py migrate. The start policy should be before deployment, and the smallest instance size should be sufficient for migrations.

Build settings and deploy

By default, Sevalla builds applications using Nixpacks, so the build strategy must be updated before your Dockerfile can be used. To update the build strategy, after you add your application, go to Settings > Update build strategy and change the build strategy from Nixpacks to Dockerfile.

Deploy on Sevalla

To deploy your app to Sevalla using Git, your code must be hosted in a Git repository. Sevalla supports any public Git repository or private repositories from GitHub, Bitbucket, and GitLab. You’ll need to connect your repo host account with Sevalla if you are using a private repo. Your repo should have a .gitignore that ignores SQLite files, .env files, virtual environments, __pycache__/, any other files that either have sensitive information or don’t need to be tracked in git. Here is an example .gitignore file:
__pycache__/ 
.env
.venv/
env/
venv/
*.sqlite3
You can now add your application in Sevalla and choose the branch and repository for your project. Ensure that you set the location for your application to match the location of your database, allowing them to communicate over an internal network. If your app requires more resources than the defaults of 0.3 GB RAM and 0.3 CPU, then switch to a larger instance size. After adding the application, you can set up the environment variables required for your app. First, go to Domains to copy your app’s generated domain. Then go to Environment variables to set up the same environment variables defined in .env except for DATABASE_URL. The values for the variables should be appropriate for production.
  • ALLOWED_HOSTS: include only the domain with no scheme or trailing slash. (e.g. deploydjangosevalla-4q4g3.sevalla.app).
  • CSRF_TRUSTED_ORGINS: include the scheme but no trailing slash. (e.g. https://deploydjangosevalla-4q4g3.sevalla.app).
  • DEBUG: should always be false except for intentional testing.
  • SECRET_KEY: should be a random string of at least 50 characters.
For the DATABASE_URL, go to Networking and click Add internal connection. Select the database you created earlier, and then select Add environment variables to the application. Rename DB_URL to DATABASE_URL and click Add internal connection.