Login

Keep settings.py in version control safely

Author:
mboersma
Posted:
March 9, 2007
Language:
Python
Version:
Pre .96
Score:
6 (after 8 ratings)

Here is a trivial way to keep your Django project in shared version control or in a public repository without exposing settings that could have security implications, and without needing to modify settings.py for your local test or production environments on checkout.

This is also a way to separate development settings from production settings, or to deploy the same code on multiple servers while only changing one site-specific "dotfile."

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#########################
# settings.py
#
# This is a Django settings file with debug set to False, and any sensitive
# variables set to empty strings.
# It can be checked in to version control or made public without fear, since
# the critical variables are loaded from a different file.

# This should always be False in production
TEMPLATE_DEBUG = DEBUG = False

# Exposing database details is a security hole, so leave them blank here.
DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
SECRET_KEY = ''

# Fill in all other, less sensitive settings as usual.
SITE_ID = 1
TIME_ZONE = 'US/Mountain'
# And so on...

# Then load those sensitive settings from a local file with tight
# filesystem permissions.
from os.path import expanduser
execfile(expanduser('~/.django-mysite-settings'))



#########################
# .django-mysite-settings
#
# Note: this is intended to be a separate file from the above code.
# This file should *not* be in version control!
#
# Ensure this file is read-only and accessible only to you and/or the
# webserver process that will need to read it.

# Set database details and credentials
DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'mydatabase'
DATABASE_USER = 'myuser'
DATABASE_PASSWORD = 'mypassword'
SECRET_KEY = ')lmy#t$-j+)=c-s6&^xe%!=anku0jmj^d$%pd0_wbgrq-v$--z'

# Maybe turn debugging on for local testing
TEMPLATE_DEBUG = DEBUG = True

# And possibly also override some debug-related settings
CACHE_BACKEND = 'dummy:///'
TEMPLATE_DIRS = (('/home/ericidle/somewhere/templates'),)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

jeffwheeler (on March 15, 2007):

You might want to remove your username and password from the .django-mysite-settings file, if that is in fact your real password. Looks like it.

#

robhudson (on March 15, 2007):

What happens when you load the project on a production machine with no file matching "~/.django-mysite-settings"? Does the execfile throw an error?

#

mboersma (on March 15, 2007):

jeffwheeler, that's a bogus login, password, and key. They shoot people for using passwords like that. I'll change my code so it's more obvious.

robhudson, yes, it will throw an error if the file isn't found. You could wrap it in a try/except, but then you'll just get an error when DATABASE_ENGINE and friends are empty strings.

This is the simplest of mechanisms, and I claim nothing lofty for it. It's my response to several Django snippets (and some projects in public version control) that work so hard to separate production from DEBUG settings, but in the process create lots of conditional code and still leave in potentially compromising settings. "Check out of svn, then don't forget to modify the settings.py" is a recipe for disaster that this at least fixes.

#

Please login first before commenting.