Django Production Settings (3) – django-environ and .env file
As explained on the previous page, we need to manage confidential data relating to the Django app settings. To separate the settings, you can use the django-environ library.
django-environ
django-environ allows you to configure the Django application using environment variables obtained from an environment file and provided by the OS.
Basically, using this library, you can separately manage confidential information in another file named .env.
Settings written in the .env file
Confidential data should be put in the .env file. Most confidential data are already included in the settings for production explained on the previous page, except SECRET_KEY
. SECRET_KEY
is not specific for production, but it should be confidentially managed and saved under the .env file.
Note: SECRET_KEY
According to the Django official documentation, SECRET_KEY
is used to provide cryptographic signing and should be set to a unique, unpredictable value. Running Django with a known SECRET_KEY
defeats many of Django’s security protections and can lead to privilege escalation and remote code execution vulnerabilities.
When you initiated the Django project, the secret key was already generated, and you can use it for production; however, you should not expose it to the public. In practice, you need to make sure that you won't push the information to the GitHub repository.
Key steps to use django-environ
Here are the key steps to use django-environ for our Django app.
1. Install django-environ
Add django-environ in requirements.txt and install the package.
Django==4.1.7
django-crispy-forms
crispy-bootstrap5
django-allauth
django-environ
As we haven't created the virtual environment, actual installation will be done later in this chapter.
2. Edit production.py
First, you need to import environ
, and add initial settings to read the .env file.
from .base import *
import environ
env = environ.Env()
env.read_env('.env')
Then, bring the settings for production from the base.py file.
And replace confidential data with env('ENVIRONMENT_VARIABLE')
. If there is a list of parameters, use env.list('ENVIRONMENT_VARIABLE')
.
Here is an example of production.py for our Django app. We don't include email settings and STATIC_ROOT
here yet. We'll explain them later.
from .base import *
import environ
env = environ.Env()
env.read_env('.env')
SECRET_KEY = env('SECRET_KEY')
DEBUG = False
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
DATABASES = {
'default': {
'ENGINE': env('DB_ENGINE'),
'NAME': env('DB_NAME'),
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'HOST': env('DB_HOST'),
'PORT': env('DB_PORT'),
}
}
And this is the example of the .env file. Make sure that the .env file is created directly under the project directory.
SECRET_KEY=django-insecure-a6e%75-^!....
ALLOWED_HOSTS=localhost,xx.xx.xx.xx
DB_ENGINE=django.db.backends.postgresql
DB_NAME=project_d
DB_USER=project_d_user
DB_PASSWORD=project_d_pass
DB_HOST=localhost
DB_PORT=5432
There are some points you need to be careful about.
- no ' ' (quotation) for all settings
- For
ALLOWED_HOSTS
, you need to put the static IP address that is attached to the Ubuntu instance. Keeplocalhost
for testing purposes. When you write more than two hosts, make sure that there are no [ ] (brackets) and no space - For database settings, make sure that the values are the same as the ones you set when you created the database.