Using environment variables to keep sensitive data out of Django settings
I was helping a new developer at my company start developing with Django. As he was going through the Django Book he felt uncomfortable about storing secret keys, password, and API keys in his settings.py file. Environment variables are the solution, but I couldn’t find any good posts out there that explain the basics.
So here is how you use environment variables to keep sensitive data out of your source code:
- Set your environment variable using the
exportcommand, like this:
import osto your settings.py file if it isn’t there already.
- Retrieve the environment variable in your settings file with this syntax:
EMAIL_HOST_PASSWORD = os.environ['DJANGO_EMAIL_PASSWORD']
Remember that the export command is specific to that terminal session. Your environment variable won’t be accessible from any other terminal windows, and it will disappear when you close the terminal window you entered it in.
You can use the
printenv command to see all environment variables defined in a session. You can use
echo to see a specific variable’s value:
echo $DJANGO_EMAIL_PASSWORD (don’t overlook the
$). You can also use
grep to filter for groups of variables:
printenv | grep DJANGO
Sometimes you want to keep a key out of source code but it’s not so sensitive that it can’t be stored on your development machine.
If you want to save yourself from manually exporting all your keys at the beginning of each development session, you can add your export statements to your virtualenv activate script.
Just edit your activate script and add your export commands to the very end. If you are using virtualenvwrapper (recommended), then you should add your export commands to the postactivate script for your virtualenv instead.
Keeping secret keys, passwords, and API keys in source code is a really bad idea, even early on in development.
From a security perspective, you never know where your source code could end up. It could be accessed wholesale off your server or a development machine. It could also be exposed through errors displayed in your app. You don’t want to hand an attacker a free pass to your critical data and services.
It’s also bad for maintainability. If your secret keys, passwords, or API keys ever change then you need to fast track a code correction to production - always risky.
I was really glad to start this practice early as a developer, and hopefully this post will help future Djangonauts find the answer a little more easily.