Environment Variables, mod_wsgi, Django & Apache

Why store your project's secret settings in an environment variable instead of your source control?

This is a simple, one-word answer. Security.

Django's settings files contain many site specific variables, including database settings, secret keys, email usernames and passwords and a host of other site settings.

For many of us that develop web applications on the regular, it is standard practice to deploy these systems in a variety of environments. These usually include (but are not limited to):

  • Production
  • Staging
  • Development
  • Local

Each of these environments are hosted on a separate EC2 instance or in a Docker container. Physical paths on each server instance may be a little different between these environments.

I prefer to use Django best practices for server settings, whether it's my local development machine (Ubuntu 14.04) or Development server (Debian 8) or Staging and Production servers (Amazon EC2/Elastic Beanstalk). This means I have my Django's webapp site settings for each environment stored in there own separate Python file.

As an example, in production, the server loads it's site settings from config/settings/production.py which in turn loads base.py (all of the site's common settings applicable to all environments). This allows me to keep my settings files inside my source control without having to constantly switch branches in order to modify these settings. Each Git branch in the SCM contains all of the server environment variable settings.

Now comes the special sauce. Apache with mod_wsgi, any settings that contain sensitive information, secret keys, usernames and/or passwords must be stored in environment variables and not the code source.

To make this as simple as possible, create a separate WSGI (Web Server Gateway Interface) file for each environment. Place the WSGI file int he same directory as Django's WSGI file. Now, create your file's content.

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.config.settings'

os.environ['DJANGO_CONFIGURATION'] = 'production'  
os.environ['DJANGO_SECRET_KEY'] = '1random_secret_code'  
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = 'your aws id'  
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = 'aws-key'  
os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME'] = 's3-bucket'  
os.environ['EMAIL_HOST_USER'] = 'email username'  
os.environ['EMAIL_HOST'] = 'email host fqdn'  
os.environ['EMAIL_HOST_PASSWORD'] = 'email password'

from django.core.wsgi.import get_wsgi_application()  
application = get_wsgi_application()  

Craig Derington

Full Stack Developer. Linux, Docker, Python, Celery, Flask, Django, Go, MySQL, MongoDB and Git. Modern, secure, high-performance applications capable of processing millions of transactions a day.

comments powered by Disqus