This question is twofold. The code and the secret keys are two different issues.
Does publishing the code affect the security of the application?
While posting the code publicly may reach attention of readers who could point security issues, it also exposes those issues to potential malicious individuals. Hiding the code doesn't make it any safer, but at least the security issues wouldn't be that obvious to find. This part of the question has already been debated and could be deemed opinion-based or duplicate.
See Gabor's answser or this SE post linked to in another answer.
How can I publish the code without exposing sensitive information?
Don't put secret stuff (passwords, secret keys,...) in the code. Those should be in a configuration file that is not in the repository. Even if the repository is private, it would be a bit dirty to keep those here.
Think of your code as an application. The website using your code is an instance of this application, with specific settings. You can have several websites sharing the same code with different settings (which makes maintenance easier, BTW).
Flask configuration pattern example
Here's what I do with Flask. I suppose a similar pattern can be used with Django, although it may provide helpers to do it differently (like django-decouple
in Vinit's answer).
Put a default_settings.py
file in the repository and override a few important settings when instantiating the application. This is a pattern described here : http://flask.pocoo.org/docs/0.12/config/#configuring-from-files.
default_settings.py
class Config():
DEBUG = False
TESTING = False
[...]
class ProductionConfig(Config):
[...]
class DevelopmentConfig(Config):
SECRET_KEY = 'dummy_key'
DEBUG = True
[...]
class TestingConfig(Config):
SECRET_KEY = 'dummy_key'
TESTING = True
[...]
Notice that I don't set a default secret key in production mode, so that if I forget to override it in the application config file, the application won't run with a dummy key.
application.wsgi
#!/usr/bin/env python3
"""Sample wsgi file
Customize path to virtual environment and you're done
"""
import os
import sys
import runpy
# Working with Virtual Environment
# see http://flask.pocoo.org/docs/0.10/deploying/mod_wsgi/
# and also https://gist.github.com/LeZuse/4032238
# and https://stackoverflow.com/questions/436198/
runpy.run_path('/path/to/venv/bin/activate_this.py')
# Add application to Python path
# Check before adding so as not to add it multiple times
# when reloading the file:
# https://code.google.com/p/modwsgi/wiki/ReloadingSourceCode
PATH = os.path.dirname(__file__)
if PATH not in sys.path:
sys.path.append(PATH)
# Set environment variable to indicate production mode
os.environ['FLASK_CONFIG'] = 'ProductionConfig'
# Provide path to custom settings file
os.environ['SETTINGS_FILE'] = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
'settings.cfg'
)
[...]
settings.cfg
# Flask secret key
# To generate a secret key:
# ''.join([random.choice(string.printable) for i in range(100)])
SECRET_KEY =
# Other secret keys
[...]
Then in the application
config_class = os.getenv('FLASK_CONFIG')
app.config.from_object(config_class)
app.config.from_envvar('SETTINGS_FILE', silent=True)
(Multi)Instantiation simplified
Using setuptools
, I can easily deploy the application in a virtualenv
. Creating an instance of the application just takes the following steps:
- create virtualenv
pip install my_app
- copy and adapt
.wsgi
example file
- copy and adapt local
settings.cfg
example file
- configure and activate website in web server (
/etc/apache2/sites-available/my_app.conf
)
The website directory on the server only contains the virtual env and the two config files that are specific to this instance.
It is fine to store example files in the repo in a docs/
directory (.wsgi
, settings.cfg
, apache .conf
file,...), with placeholders for parameters.