Best Practices for Securing Django in Production


Deploying Django in production requires careful security configurations, especially when using cloud platforms like AWS, DigitalOcean, GCP, or Azure. While Django provides security features out of the box, a misconfigured production environment can expose your application to attacks.
This guide will expand on common security mistakes and how to configure Django securely in production with best practices for AWS, DigitalOcean, GCP, and other cloud platforms.
1. Setting Up Django’s Production Security Configurations
1.1 Disable Debug Mode
Leaving DEBUG=True
in production is a major security risk. It exposes environment variables, database credentials, and internal stack traces.
Fix:
import os
DEBUG = os.getenv("DJANGO_DEBUG", "False") == "True"
ALLOWED_HOSTS = ["yourdomain.com"]
Use environment variables to manage settings securely instead of hardcoding them.
1.2 Restrict Allowed Hosts
Only allow requests from your domain:
ALLOWED_HOSTS = ["yourdomain.com", "api.yourdomain.com"]
For cloud-based environments (AWS/GCP), set ALLOWED_HOSTS
dynamically:
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "").split(",")
2. Securing Database in Production
2.1 Secure Database Credentials Using Environment Variables
Never hardcode database credentials in settings.py
. Instead, store them in AWS SSM Parameter Store, GCP Secret Manager, DigitalOcean App Secrets, or .env
files.
Example for AWS RDS / PostgreSQL:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv("DB_NAME"),
'USER': os.getenv("DB_USER"),
'PASSWORD': os.getenv("DB_PASSWORD"),
'HOST': os.getenv("DB_HOST"), # RDS instance or Cloud SQL
'PORT': os.getenv("DB_PORT", "5432"),
'OPTIONS': {
'sslmode': 'require', # Enforce SSL
},
}
}
2.2 Use IAM Roles for RDS (AWS)
Instead of storing passwords, use IAM authentication with AWS RDS:
psql "host=your-rds-instance.amazonaws.com dbname=yourdb sslmode=verify-full sslrootcert=rds-ca.pem"
2.3 Enable SSL for Database Connections
For PostgreSQL on AWS RDS, DigitalOcean DBaaS, or GCP Cloud SQL, enforce SSL to encrypt data in transit.
'OPTIONS': {
'sslmode': 'require',
}
Verify with:
psql "sslmode=require"
3. Securing Static and Media Files
3.1 Use a CDN for Static & Media Files
Serving static and media files via S3, DigitalOcean Spaces, or Google Cloud Storage (GCS) reduces server load and increases security.
Example for AWS S3:
INSTALLED_APPS += ["storages"]
AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME")
AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com"
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
For DigitalOcean Spaces:
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
AWS_S3_ENDPOINT_URL = "https://nyc3.digitaloceanspaces.com"
For Google Cloud Storage (GCP):
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_BUCKET_NAME = os.getenv("GS_BUCKET_NAME")
3.2 Restrict Public Access to Sensitive Files
Set private permissions for user-uploaded files.
Use pre-signed URLs for downloads.
AWS_S3_OBJECT_PARAMETERS = {
"CacheControl": "max-age=86400",
"ACL": "private"
}
4. Secure Authentication & Sessions
4.1 Use Secure Password Hashing
Enable Argon2 for better security:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
]
4.2 Enforce HTTPS for Sessions
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
4.3 Enable Multi-Factor Authentication (MFA)
Use django-otp for MFA in Django Admin:
pip install django-otp
Add to INSTALLED_APPS
:
INSTALLED_APPS += ["django_otp", "django_otp.plugins.otp_totp"]
5. Protect Against SQL Injection & XSS
5.1 Prevent SQL Injection
Always use ORM or parameterized queries:
cursor.execute("SELECT * FROM users WHERE username = %s", [username])
5.2 Prevent Cross-Site Scripting (XSS)
Use Django’s auto-escaping in templates.
Enable content security policy (CSP) middleware:
pip install django-csp
Add CSP Headers:
MIDDLEWARE += ["csp.middleware.CSPMiddleware"]
CSP_DEFAULT_SRC = ["'self'"]
CSP_SCRIPT_SRC = ["'self'", "'unsafe-inline'"]
6. Configure Web Server Security
6.1 Use Gunicorn for Deployment
gunicorn --workers 3 myproject.wsgi
6.2 Harden Nginx Configuration
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
7. Enforce Logging & Monitoring
7.1 Configure Django Logging
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"file": {
"level": "ERROR",
"class": "logging.FileHandler",
"filename": "/var/log/django_errors.log",
},
},
"loggers": {
"django": {
"handlers": ["file"],
"level": "ERROR",
"propagate": True,
},
},
}
7.2 Use AWS CloudWatch for Logs
For AWS ECS or EC2, install CloudWatch Agent:
sudo yum install amazon-cloudwatch-agent
Configure awslogs
:
[general]
state_file = /var/awslogs/state/agent-state
[/var/log/django]
file = /var/log/django_errors.log
log_group_name = django_logs
Start logging service:
sudo systemctl start awslogs
8. Set Up Firewalls & DDoS Protection
8.1 Restrict Database Access
For AWS RDS, create security groups:
aws ec2 authorize-security-group-ingress --group-id sg-12345 --protocol tcp --port 5432 --source-ip your-server-ip/32
For DigitalOcean, enable Cloud Firewalls.
For GCP, restrict database access using VPC firewall rules.
8.2 Use AWS WAF for DDoS Protection
aws waf create-web-acl --name MyWebACL
For Cloudflare, enable DDoS protection under Firewall Rules.
Final Thoughts
Securing Django in production requires configuring security settings, using cloud-native security tools, and continuously monitoring vulnerabilities. Whether deploying on AWS, DigitalOcean, GCP, or other platforms, follow these best practices to keep your application secure.
Feel free to reach me at AhmadWKhan.com to discuss your application’s security issues.
Subscribe to my newsletter
Read articles from Ahmad W Khan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
