Skip to main content

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:

  1. Security: Keeps sensitive information out of your codebase
  2. Environment-specific configuration: Different settings for development, staging, and production
  3. Portability: Makes your application easier to deploy across different environments
  4. 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:

python
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

bash
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

python
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

bash
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

python
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:

bash
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:

yaml
# 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:

bash
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:

bash
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:

  1. Never commit .env files to version control
  2. Rotate secrets regularly - especially if they might have been compromised
  3. Use secret management services for production environments:
    • AWS Secrets Manager
    • HashiCorp Vault
    • Azure Key Vault
    • Google Secret Manager

Best Practices

  1. Default values: Always provide sensible defaults for non-sensitive settings
  2. Type casting: Remember that environment variables are strings by default
  3. Configuration validation: Validate required environment variables on startup
  4. Documentation: Document all environment variables your application uses

Here's an example of validating required environment variables:

python
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:

python
# 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 and django-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

Exercises

  1. Convert a Django project's settings.py to use environment variables for sensitive configuration.
  2. Set up a local development environment with django-environ and a .env file.
  3. Create a script that validates required environment variables on application startup.
  4. Implement different environment variable configurations for development, testing, and production environments.
  5. 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! :)