Environment Variables & Secrets0%

Environment Variables & Secrets

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Environment Variables & Secrets

Hardcoding sensitive credentials—such as database passwords, Stripe API keys, AWS secret tokens, and Django's SECRET_KEY—directly into source code files is one of the most severe security vulnerabilities in software engineering. If source code is pushed to public repositories or shared across teams, exposed credentials allow attackers to compromise production systems. Professional Django architectures use Twelve-Factor App Environment Configuration.


1. The Twelve-Factor Configuration Principle

"Store config in the environment." — The Twelve-Factor App

A codebase should be completely decoupled from environment credentials. The exact same container image or git commit should run in:

  • Local Development: Reading local SQLite and mock API keys.
  • Staging: Reading staging PostgreSQL and sandbox payment gateways.
  • Production: Reading production RDS clusters and live payment credentials.

2. Managing Environments with python-dotenv

In local development, store secrets in a .env file at the root of your project:

Bash / Terminal
# .env (MUST BE ADDED TO .gitignore!)
DJANGO_SECRET_KEY="django-insecure-enterprise-super-secret-key-12345"
DJANGO_DEBUG="True"
DJANGO_ALLOWED_HOSTS="localhost,127.0.0.1"
 
# Database connection URL
DATABASE_URL="postgres://postgres:secret123@localhost:5432/enterprise_db"
 
# Third-Party API Keys
AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
STRIPE_SECRET_KEY="sk_test_51Mz..."

3. Integrating .env in settings.py

Use python-dotenv or django-environ:

Bash / Terminal
pip install python-dotenv dj-database-url
Python
# config/settings.py
import os
from pathlib import Path
from dotenv import load_dotenv
import dj_database_url
 
BASE_DIR = Path(__file__).resolve().parent.parent
 
# Load .env file if it exists
load_dotenv(BASE_DIR / ".env")
 
# 1. Secret Key (Crash if missing in production!)
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
 
# 2. Debug Flag (Defaults to False if unset)
DEBUG = os.environ.get("DJANGO_DEBUG", "False").lower() in ["true", "1", "yes"]
 
# 3. Allowed Hosts list parsing
ALLOWED_HOSTS = [
host.strip()
for host in os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")
if host.strip()
]
 
# 4. Database configuration via dj-database-url
# Parses postgres://user:pass@host:port/dbname into Django DATABASES dict
DATABASES = {
"default": dj_database_url.config(
default=f"sqlite:///{BASE_DIR / 'db.sqlite3'}",
conn_max_age=600, # Database connection pooling for performance
)
}

4. Git Hygiene: .gitignore and .env.example

To ensure teammates know which environment variables are required without exposing secrets, commit a template .env.example:

Bash / Terminal
# .env.example (Safe to commit to Git!)
DJANGO_SECRET_KEY=
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
DATABASE_URL=postgres://user:password@localhost:5432/dbname
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

And guarantee .env is ignored in .gitignore:

Output
# .gitignore
.env
.env.local
*.log
db.sqlite3

Interactive Quiz

Practice Quiz

Question 1
What is the primary security danger of committing SECRET_KEY to a Git repository?
Question 2
What is the purpose of committing a .env.example file while ignoring .env in .gitignore?
Question 3
What does the dj-database-url package do?
Question 4
What does conn_max_age=600 configure when setting up databases?
Question 5
In production environments like Docker or Kubernetes, how should environment variables be passed?
Next Lesson

Full Web Application

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext