DEV Community

Joshua Masiko
Joshua Masiko

Posted on

How to Keep Secrets out of Django Settings

Introduction

The Django startproject command creates a settings file that includes values that should be kept secret. These include:

  • SECRET_KEY is a value used when generating sessions and password reset tokens.

  • DATABASE_SETTINGS specifies the database connection settings and may include database credentials.

The DEBUG setting is also of interest:
DEBUG is a boolean value which determines whether Django displays detailed tracebacks are displayed when exceptions are raised.

The deployment checklist recommends that:

  • DEBUG be set to False to avoid leaking sensitive information from the detailed tracebacks that Django displays
  • Secrets and database credentials be kept out of source control.

This is also consistent with the Twelve-factor recommendation to keep Config separate from Code.

Twelve-factor is a useful set of recommendations for building web applications.

Django-environ

Django-environ is a third-party Django library that can be used to manage environment variables.
Values are read on startup instead of hardcoded in the settings file. The benefits include:

  • Your don't have to use multiple settings files to manage different deployments (e.g staging, production, developer).
  • Secrets can be kept out of source control.

It reads values from a .env file in the same folder as settings.py.

Instructions

Note: In the instructions below .env.example and .env should be saved in the same folder as settings.py

Install django-environ

pip install django-environ

Add a .env.example file with these contents:

DEBUG=on
SECRET_KEY=your-secret-key
DATABASE_URL=psql://urser:urpassword@127.0.0.1:8458/database

This file is an example for collaborators to follow when creating the .env file for their local environment.

Add .env to your .gitignore file to prevent it from being added to the repository

At the top of your settings.py add the following:

import environ
env = environ.Env(
    # set casting, default value
    DEBUG=(bool, False)
)
# reading .env file
environ.Env.read_env()

Change the DEBUG, SECRET_KEY and DATABASES lines in settings.py to read their values from the environment.

DEBUG = env('DEBUG')
...
SECRET_KEY = env('SECRET_KEY')
...

DATABASES = {
    'default': env.db(),
}

Your can then add .env.example and the the modified settings file to the Git repository

git add .

git commit -m "Extracted secrets from the settings file"

For each deployment (staging, production, developer environment) you then:

Create a .env file with the settings specific to that environment. These include:

  • Your desired DEBUG setting.
  • The secret key.
  • Your DATABASE connection string and credentials.

Django has a utility function that the startproject command uses to generate the secret
You can use it from the command line.
With your virtual environment activated run this command:

python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'

It will spit out a random string like:

a1$%jr29f2(u^l=r1q1a2$sztg%x7%g8s@!ne#_(^5$woi#wi$

Assuming your DATABASE setting was

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'blog',
        'USER': 'dbuser',
        'PASSWORD': 'dbpassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Your .env file would look like

DEBUG=on
SECRET_KEY=a1$%jr29f2(u^l=r1q1a2$sztg%x7%g8s@!ne#_(^5$woi#wi$
DATABASE_URL=psql://dbuser:dbpassword@127.0.0.1:5432/blog

Note that there are not quotes around the values in the .env file

For your production deployment change DEBUG=on to DEBUG=off

You can confirm that your app starts up successfully by running the Django Dev Server

python manage runserver

If there are any errors consult the Django-environ documentation for guidance.

Top comments (2)

Collapse
 
deepakgd profile image
Deepak Govindarajan

Thank you

Collapse
 
soniarpit profile image
Arpit • Edited

is it possible without django-environ?