Django logo

How to provision a Django application with secrets

Every new Django project comes with a hardcoded SECRET_KEY in settings.py:

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'p0lx_5n@$+2yyc&(bz!t=t&*w55ed#-wecor+brcf#2k^h(bl!'

You don’t want this in source control, right? Common practice is to load it from an environment variable:

SECRET_KEY = os.getenv('APPNAME_SECRET_KEY')

While this removes hardcoded secrets from source code, it doesn’t solve your problem completely; It just moves the problem one layer up the stack. Now you need to find a way to provision the environment with the secrets your app needs.

This guide will show how to automatically and securely provision a Django application with the secrets it needs, without placing them in source code or leaking them along the CI/CD pipeline.

Diagram showing secret provisioning to a Django application with SecretHub

Before you begin

Before you start, make sure you have completed the following steps:

  1. Install the SecretHub CLI for your OS.
  2. Sign up for a SecretHub account.
  3. Install Python and Django
  4. Create a new Django project
  5. Load the secret key in settings.py from an environment variable, as shown in the introduction:
    SECRET_KEY = os.getenv('APPNAME_SECRET_KEY')
    

Step 1: Provision at runtime

Let’s create a secret key for the app and add it to SecretHub:

secrethub generate --symbols --length=50 your_company/app_name/secret_key

The run command can be used to provision a command with secrets in environment variables:

secrethub run [options] -- <command>

You can wrap manage.py runserver to provision your Django app with the environment variable:

secrethub run -e APPNAME_SECRET_KEY=your_company/app_name/secret_key -- manage.py runserver

You have now provisioned the app without having any secret checked into source control! 🎉

On production, it works exactly the same. You can wrap gunicorn, uwsgi or anything else you are using with secrethub run:

secrethub run -e APPNAME_SECRET_KEY=your_company/app_name/secret_key -- gunicorn app_name.wsgi

Step 2: Codify the environment

Instead of mapping the environment variables to the SecretHub paths in the command, you can also use a secrethub.env file:

APPNAME_SECRET_KEY = {{ your_company/app_name/secret_key }}

Now you can just use

secrethub run -- manage.py runserver

to run the app.

You can now provision the app without having any secret checked into source control! 🎉

See also