Github, secret keys and other local settings

How to make sure your project's passwords don't end up on the internet.

July 5, 2020, 2:32 p.m.

Most of you will be familiar with Github and will know that you shouldn't put things like secret keys, email passwords, database passwords etc. in your repository. There are many ways to do that, some use separate programs for that, some manually adjust settings files. There is a fairly straightforward approach used by Wagtail that we will explain below: put all common settings in a file base.py, all specific non-secret development settings in dev.py, all specific non-secret production settings in production.py and only the secret settings in a file local.py that exists locally and on the server, but is never uploaded to Github.

To show how that works we will use our pet project as an example; it will work the same way for any project. We will briefly show how to set up a repository for the project; if you are familiar with that, skip ahead.

This might also be a good time to create your README.md and license file. Make a README.md file, put a # sign on the first line, followed by the title of your project. There are many options for licenses, the MIT license is very common, so make a file MIT-LICENSE.txt, copy the license text and paste it in the file.

Create a git repository; we will call ours pet. Copy the <link> to the repository. Go to the project directory on your computer. Type in the following commands:

git init
git remote add origin <link>

This initializes git in your project directory and ties it to the remote repository. The next thing to do is tell git what to synchronize, or better, what NOT to synchronize, in the .gitignore file. Create the file and add at least the following content (full content available):

db.sqlite3
env/
.env
local.py
*.mo
.coverage
media/**

Most of what we don't want in our repository is self-explanatory: database files, virtual environment files, translation compilation (*.mo), test results (.coverage). We don't want media files either, because it will take up unnecessary space, we need to upload them directly to our production server anyway and pulling media files from the repository might cause conflicts. But do make sure you backup your media files! We'll come back to the local.py settings file in a minute. First type the following:

git add .
git commit -m "initial commit"
git push -u origin master

All content is now in your remote repository. Every time you want to update your remote repository, repeat the last three commands (with "initial commit" replaced by a meaningful message). There are lots of tutorials on git available, so we leave it at this.

On to our local.py file. Wagtail intends to use this file for local settings that should never be tracked, such as secret keys and passwords. Development settings are in dev.py, if you check this file then you see that as a last step it tries to import local.py. The secret key is also in dev.py. So create local.py and let's put a (truly) secret key in there that will not be tracked. Django has a function for that. Open the Django shell with:

python3 manage.py shell

At the prompt type:

from django.core.management.utils import get_random_secret_key
get_random_secret_key()

Copy the string with the secret key and leave the shell with Ctrl-D. Put in local.py:

SECRET_KEY = '<the secret key>'

This will override the one in dev.py. In production, we have to copy the local.py manually to the server once; since production.py also imports local.py, the secret key will be available for production as well.

The same is valid for your database settings. If your database settings are in base.py, take them out and paste them in your local.py file. If you want to change the password of the user, type psql postgres to go to the psql command prompt and type:

ALTER USER usr_pet WITH PASSWORD '<new password>';

Note: for automatic testing Travis needs a working remote production environment, so when using Travis we will have to add a few minimal settings; but that's for later worry.

We'll also put our email settings for authentication in local.py; if you want to know more, read on.

Comment on this article (sign in first or confirm by name and email below)