Environment variables allow you to separate configuration from code, which is particularly important for storing sensitive data like API keys, database credentials, and secret keys. In Django, this helps to keep sensitive information such as the SECRET_KEY
and database connection details out of your source code, which is essential for security.
By using environment variables, you ensure that your application can behave differently based on the environment it’s running in (e.g., development, staging, production), making it easy to manage different configurations without changing the codebase.
In Django, a common use case for environment variables is storing the SECRET_KEY
, which is critical for cryptographic signing (such as for sessions or cookies). Hardcoding this value in the settings file is unsafe, especially if the codebase is shared publicly (e.g., on GitHub). Instead, you can store it in an environment variable and load it from there.
Here’s how you can manage the SECRET_KEY
securely with environment variables:
In your terminal (or your hosting service), set the environment variable. For local development, you can set it manually or use .env
files to load environment variables.
export DJANGO_SECRET_KEY='your-very-secure-secret-key'
python-decouple
(Optional but Recommended)While you can use the built-in os
module to access environment variables, it’s often more convenient to use libraries like python-decouple
to manage settings. This library allows you to load variables from a .env
file, making it easier to work with configuration in multiple environments.
To install it, run:
pip install python-decouple
settings.py
You can then import the environment variable into your settings.py
file using python-decouple
or os
. Here’s how:
Using python-decouple
:
from decouple import config
SECRET_KEY = config('DJANGO_SECRET_KEY')
Using os
:
import os
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
This retrieves the DJANGO_SECRET_KEY
from your environment variables.
.env
File for Local Development (Optional)If you don’t want to set environment variables manually every time, you can create a .env
file in your project root and store the keys there. For example, create a .env
file:
DJANGO_SECRET_KEY=your-very-secure-secret-key
Ensure that this .env
file is added to .gitignore
so it’s not pushed to version control.
With python-decouple
, environment variables in .env
files are automatically loaded, so the above code will work without any further changes.
Another common use case for environment variables is configuring database connections. Instead of hardcoding your database credentials, you can set the database settings via environment variables.
First, add your database credentials as environment variables:
export DB_NAME='mydb'
export DB_USER='myuser'
export DB_PASSWORD='mypassword'
export DB_HOST='localhost'
export DB_PORT='5432'
Then, in your settings.py
:
from decouple import config
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': config('DB_PORT', default='5432'),
}
}
This allows you to change your database configuration by simply modifying environment variables instead of touching the settings.py
file, making it easier to manage different configurations for different environments.
Apart from the SECRET_KEY
and database credentials, you might have other sensitive data like API keys or third-party service credentials. Using environment variables for all sensitive data makes your application more secure.
API_KEY = config('MY_API_KEY')
Now, you can set your API key in an environment variable:
export MY_API_KEY='your-api-key-here'
In production environments (like on a cloud server), you will typically set these environment variables in the hosting service’s configuration interface (e.g., AWS, Heroku, DigitalOcean, etc.). The approach will vary depending on the platform, but the principle remains the same: keep sensitive data out of your code and instead load it from environment variables.
If you’re using Heroku, you can set environment variables via the Heroku CLI:
heroku config:set DJANGO_SECRET_KEY='your-very-secure-secret-key'
If you’re using Docker, you can pass environment variables through a .env
file or directly in the docker-compose.yml
file.
Example using a .env
file:
# .env file
DJANGO_SECRET_KEY=your-very-secure-secret-key
Then, in your docker-compose.yml
:
version: '3'
services:
web:
image: django-app
env_file:
- .env
ports:
- "8000:8000"
This ensures that your Django application will read the environment variables from the .env
file when the container is started.
For managing secret keys across different environments (e.g., development, staging, production), it’s a good practice to store environment variables for each environment separately. You can use different .env
files, one for each environment, and load them conditionally.
Create different .env
files like .env.dev
, .env.prod
, and load the appropriate file based on the environment:
# .env.dev
DJANGO_SECRET_KEY=dev-secret-key
# .env.prod
DJANGO_SECRET_KEY=prod-secret-key
You can then load the right file in your Django application by using the python-decouple
library or django-environ
to manage these files and automatically switch based on the environment. Here’s an example using django-environ
:
import environ
env = environ.Env()
environ.Env.read_env() # Read .env file
SECRET_KEY = env('DJANGO_SECRET_KEY')
This allows you to easily manage different secret keys for different environments.
.env
files for local development: They make it easier to manage different configurations locally..env
files out of version control: Ensure that your .env
files are included in .gitignore
so they are not accidentally pushed to a public repository.