Django Environment Variables
When deploying Django applications, it's crucial to properly manage configuration settings like database credentials, API keys, and other sensitive information. Environment variables provide a secure way to handle these configurations without hardcoding them in your source code.
Why Use Environment Variables?
Environment variables offer several advantages for Django applications:
- Security: Keeps sensitive information out of your codebase
- Environment-specific configuration: Different settings for development, staging, and production
- Portability: Makes your application easier to deploy across different environments
- Best practices: Follows the principles in the Twelve-Factor App methodology
Basic Environment Variable Usage in Django
Django can access environment variables through Python's os
module.
Let's see a simple example of how to use environment variables in your settings.py
file:
import os
# Reading a secret key from environment variable
SECRET_KEY = os.environ.get('SECRET_KEY', 'default-development-key')
# Database configuration using environment variables
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'mydatabase'),
'USER': os.environ.get('DB_USER', 'myuser'),
'PASSWORD': os.environ.get('DB_PASSWORD', 'mypassword'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# Setting DEBUG based on environment variable
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
In the example above, the os.environ.get()
method is used to retrieve environment variables. The second parameter is a default value that's used if the environment variable isn't set.
Using python-dotenv for Local Development
While production environments typically set environment variables at the system level, it's more convenient to use a .env
file for local development.
Let's set this up with python-dotenv
:
Step 1: Install python-dotenv
pip install python-dotenv
Step 2: Create a .env file in your project root
SECRET_KEY=your-secret-key-here
DEBUG=True
DB_NAME=mydatabase
DB_USER=myuser
DB_PASSWORD=mypassword
DB_HOST=localhost
DB_PORT=5432
Step 3: Update settings.py to load the .env file
import os
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Now you can use environment variables as before
SECRET_KEY = os.environ.get('SECRET_KEY', 'default-development-key')
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
# Rest of your settings...
Step 4: Add .env to .gitignore
# .gitignore
.env
This ensures your sensitive information doesn't accidentally get committed to your repository.
Using django-environ for More Comprehensive Environment Management
django-environ
is a package that combines the functionality of python-dotenv
with additional features specifically designed for Django projects.
Step 1: Install django-environ
pip install django-environ
Step 2: Create a .env file (similar to before)
SECRET_KEY=your-secret-key-here
DEBUG=True
DATABASE_URL=postgres://myuser:mypassword@localhost:5432/mydatabase
EMAIL_URL=smtp://[email protected]:[email protected]:587/?tls=True
CACHE_URL=redis://user:password@redis:6379/1
Step 3: Update settings.py to use django-environ
import environ
# Initialize environ
env = environ.Env(
# Set default values
DEBUG=(bool, False),
)
# Read .env file if it exists
environ.Env.read_env()
# Use environment variables in settings
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
# Parse database URL
DATABASES = {
'default': env.db(),
}
# Parse email URL
EMAIL_CONFIG = env.email_url()
vars().update(EMAIL_CONFIG)
# Parse cache URL
CACHES = {
'default': env.cache(),
}
The django-environ
package provides convenient methods like env.db()
, env.email_url()
, and env.cache()
that parse the URL format and convert it into the appropriate Django settings.
Environment Variables in Production
When deploying your application to production, you'll need to set environment variables at the system level. Here's how to do it for different deployment platforms:
1. Traditional Linux Server
Set environment variables in a system configuration file or directly before running the application:
export SECRET_KEY="your-secret-key-here"
export DEBUG="False"
export DATABASE_URL="postgres://user:password@localhost:5432/mydatabase"
You can add these to /etc/environment
or to your application's service file if using systemd.
2. Docker
In a Dockerfile
or docker-compose.yml
file:
# docker-compose.yml
services:
web:
build: .
environment:
- SECRET_KEY=your-secret-key-here
- DEBUG=False
- DATABASE_URL=postgres://user:password@db:5432/mydatabase
3. Heroku
Using the Heroku CLI:
heroku config:set SECRET_KEY="your-secret-key-here"
heroku config:set DEBUG="False"
heroku config:set DATABASE_URL="postgres://user:password@host:5432/database"
Or set them through the Heroku dashboard under Settings → Config Vars.
4. AWS Elastic Beanstalk
Using the AWS CLI:
aws elasticbeanstalk update-environment --environment-name my-env --option-settings \
Namespace=aws:elasticbeanstalk:application:environment,OptionName=SECRET_KEY,Value="your-secret-key-here" \
Namespace=aws:elasticbeanstalk:application:environment,OptionName=DEBUG,Value="False"
Or set them through the AWS Elastic Beanstalk console under Configuration → Software.
Handling Sensitive Information
Some important guidelines for managing sensitive information:
- Never commit .env files to version control
- Rotate secrets regularly - especially if they might have been compromised
- Use secret management services for production environments:
- AWS Secrets Manager
- HashiCorp Vault
- Azure Key Vault
- Google Secret Manager
Best Practices
- Default values: Always provide sensible defaults for non-sensitive settings
- Type casting: Remember that environment variables are strings by default
- Configuration validation: Validate required environment variables on startup
- Documentation: Document all environment variables your application uses
Here's an example of validating required environment variables:
import os
from django.core.exceptions import ImproperlyConfigured
def get_env_variable(var_name):
"""Get the environment variable or raise an exception."""
try:
return os.environ[var_name]
except KeyError:
error_msg = f"Set the {var_name} environment variable"
raise ImproperlyConfigured(error_msg)
# This will raise an error if SECRET_KEY is not set
SECRET_KEY = get_env_variable('SECRET_KEY')
Common Django Settings to Configure via Environment Variables
Here's a list of Django settings commonly configured through environment variables:
# Security settings
SECRET_KEY = os.environ.get('SECRET_KEY')
DEBUG = os.environ.get('DEBUG') == 'True'
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
# Database settings
DATABASES = {
'default': {
'ENGINE': os.environ.get('DB_ENGINE', 'django.db.backends.sqlite3'),
'NAME': os.environ.get('DB_NAME', BASE_DIR / 'db.sqlite3'),
'USER': os.environ.get('DB_USER', ''),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': os.environ.get('DB_HOST', ''),
'PORT': os.environ.get('DB_PORT', ''),
}
}
# Email settings
EMAIL_BACKEND = os.environ.get('EMAIL_BACKEND', 'django.core.mail.backends.smtp.EmailBackend')
EMAIL_HOST = os.environ.get('EMAIL_HOST', 'localhost')
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 25))
EMAIL_USE_TLS = os.environ.get('EMAIL_USE_TLS', 'False') == 'True'
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '')
# Third-party service credentials
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', '')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', '')
STRIPE_API_KEY = os.environ.get('STRIPE_API_KEY', '')
Summary
Environment variables are an essential tool for managing configuration in Django applications. They help keep your sensitive information secure and make your application more portable across different environments.
In this guide, we've covered:
- Basic usage of environment variables in Django
- Using
python-dotenv
anddjango-environ
for local development - Setting environment variables in production environments
- Best practices for handling sensitive information
- Common Django settings to configure via environment variables
By implementing these practices, you'll have a more secure, maintainable, and deployable Django application.
Additional Resources
- The Twelve-Factor App: Config
- Django Settings Best Practices
- django-environ Documentation
- python-dotenv Documentation
Exercises
- Convert a Django project's
settings.py
to use environment variables for sensitive configuration. - Set up a local development environment with
django-environ
and a.env
file. - Create a script that validates required environment variables on application startup.
- Implement different environment variable configurations for development, testing, and production environments.
- Research and implement a specific deployment platform's environment variable system (e.g., Heroku, Docker, or AWS).
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)