Django和部署中的私有设置

时间:2015-10-16 20:57:04

标签: python django security deployment fabric

我正在使用Django并使用Ansible部署我的堆栈。最后,我使用Fabric来部署我的Django项目,从GitHub中提取我的代码。

我的问题:在Django的settings.py文件中处理私人设置的最佳做法是什么,例如电子邮件或S3的密码?目前,我在部署脚本结束时将settings_production.py从我的机器文件传输到生产机器,然后重新启动应用程序服务器。此文件包含我没有将settings.py作为repo的一部分放入的设置。

在我的settings.py结尾处我添加了类似

的内容
try:
    from settings_production import *
except ImportError:
    pass

有更好的方法吗?

4 个答案:

答案 0 :(得分:7)

答案是:http://12factor.net/config

您应该通过不同的设置模块管理环境之间与代码相关的差异。这方面的一个示例是在本地将debug_toolbar添加到INSTALLED_APPS,同时在生产中将其删除。要处理此方面,而不是使用旧的try: import except ImportError: ...惯用语并在本地计算机上保留版本控制local_settings.py,您应该将所有设置模块保留在版本控制中,包括你的本地设置。然后,在wsgi.pymanage.py中,使用os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.conf.local')默认您的项目使用本地设置。在dev / production中,添加一个环境变量以使用相应的设置模块(例如DJANGO_SETTINGS_MODULE=myproject.conf.dev)。

当您使用12 Factor时,不再需要保留某些设置模块不受版本控制,因为使用12 Factor,您不会将任何密码或敏感设置直接放入设置模块。您可以将它们保存在环境中并按以下方式访问它们:

# Inside of a settings module
FOO_PASSWORD = os.environ['FOO_PASSWORD']

Heroku等环境中,此设置很简单,因为您可以通过网络界面为您的应用输入config vars

我推荐几乎所有12 Factor的原则,特别是disposabilitylogsconfig等内容。

合理的牺牲

如果你想维护一个额外的设置模块,不受版本控制,以避免在本地开发期间使用环境变量(我不怪你),你仍然可以遵循上述原则并且还在版本控制中{em> 的本地设置模块的底部添加try: from some_other_local import * except: pass。这将允许您在本地设置仅必要的覆盖设置,同时仍保留本地设置的其余部分(例如,本地数据库,相对静态/媒体文件路径,已安装的应用程序等),从而为您提供最佳两个世界。

额外资源

答案 1 :(得分:1)

我认为如何做到这一点的一个很好的例子是jcalazan/ansible-django-stack,除了代码之外还包含一些链接,特别是关于How to deploy encrypted copies of your SSL keys and other files with Ansible and OpenSSL的链接。

答案 2 :(得分:0)

我认为您可以创建一个settings.py,然后在那里:

try:
    from local_settings import *
except ImportError:
    pass

你必须把它放在settings.py的结尾处。对于您的开发环境,您创建local_settings.py,在那里您将所有生产配置覆盖到您当地的东西。通过这种方式,您可以跟踪生产设置的变化,同时保持本地的灵活性。

唯一的问题是,如果您不小心忘记覆盖settings.py中的local_settings.py,您最终可能会使用可能有害的生产设置。

对我而言,我只是在我的本地~/.bashrc中添加此内容,以确保django始终使用local_settings.py

export DJANGO_SETTINGS_MODULE=app.settings.local_settings

编辑:

如果您不想回购以跟踪更改并且您不想触摸生产服务器,我认为没有更好的方法来复制设置文件。毕竟,您的更改必须以某种方式从您的计算机移动到生产中!也许您可以rsync该文件,但它并不比结构put好,对吧?

答案 3 :(得分:0)

所有配置都应使用环境变量完成,因为:

  1. 与语言无关
  2. 通常不大可能偶然将它们检查到源代码控制中
  3. 在某些部署环境中,这是唯一可用的配置形式

因此,想法是使用env var标志使您的部署完全可配置。

在开发环境中,direnv是通过目录设置环境变量的简便方法。

您还可以使用一种机制,允许开发人员在其开发环境中使用gitignored python文件覆盖设置:

# the manage.py file
import os

if __name__ == '__main__':
    if os.path.isfile('local_overrides.py'):
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'local_overrides')
    else:
        os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
    execute_from_command_line(sys.argv)

和local_overrides文件:

# the local_overrides.py file
import os

os.environ["DB_NAME"] = "abc"
from settings import *
INSTALLED_APPS.append('xyz')

请注意,这与建议在末尾添加try / import的其他答案不同。在这里,local_overrides文件具有完全控制权,此设置具有三个优点:

  1. 您可以使用os.environ方便地从python文件中从设置模块导入之前设置env vars
  2. 由于它在python文件中,因此会触发热重载,而其他环境变量操作工具则需要重新启动开发服务器
  3. 您可以从任意数量的设置模块中导入,从而更容易进行实验

这符合12factor的建议,但增加了开发人员的便利性。

请注意,针对每个环境,建议12factor反对设置模块。我会争辩说环境和“运行模式”之间存在本质上的三个区别:在服务器上,在开发模式下或作为单元测试。

因此,请避免将“生产”设置作为python模块使用,而应将“服务器”作为服务于所有服务器环境的python模块,因为它们具有相似之处,但可以使用粒度env var来区分它们。