【问题标题】:Private settings in Django and DeploymentDjango 和部署中的私有设置
【发布时间】:2016-01-15 17:37:25
【问题描述】:

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

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

在我的 settings.py 末尾,我添加了类似的内容

try:
    from settings_production import *
except ImportError:
    pass

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: python django security deployment fabric


    【解决方案1】:

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

    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 文件从设置模块导入之前设置环境变量@
    2. 因为它在 python 文件中,它会触发热重新加载,而其他 env var 操作工具需要重新启动您的开发服务器
    3. 您可以从任意数量的设置模块中导入,这样可以更轻松地进行实验

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

    请注意,12factor 建议针对每个环境的设置模块。我认为环境和“运行模式”之间存在差异,其中基本上有三种:在服务器上、在开发模式下或作为单元测试。

    因此,请避免将“生产”设置作为 Python 模块,而更喜欢将“服务器”设置为为所有服务器环境提供服务的 Python 模块,因为它们有相似之处,但使用精细的 env var 将它们彼此区分开来。

    【讨论】:

      【解决方案2】:

      答案是: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') 将您的项目默认为使用本地设置。在开发/生产中,您添加一个环境变量以使用相应的设置模块(例如,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

      合理的牺牲

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

      额外资源

      【讨论】:

      • 这对我很有效。除了:如果我通过 Supervisor 的 (environment=) 设置将我的 SECRET_KEY 部署为环境变量,我将失去在服务器上执行 Django 内务管理任务的能力。 python manage.py collectstatic 失败:ImproperlyConfigured("The SECRET_KEY setting must not be empty.")。任何建议如何正确设置。或调用 manage.py。
      • @FalkSchuetzenmeister 你可以通过export将它们添加到你的shell环境中
      • 是的,这似乎违背了在我的主管配置文件中设置环境变量的目的,因为我必须在另一个地方设置它们。
      • @FalkSchuetzenmeister 理想的解决方案是通过单独的服务管理您的环境变量,并通过 supervisord 以及 .bash_rc 脚本连接到该服务,但同时您可以手动输入它们而不必设置所有这些
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我认为你可以创建一个settings.py,然后在其中进行操作:

        try:
            from local_settings import *
        except ImportError:
            pass
        

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

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

        对我来说,我只需将其添加到我的本地 ~/.bashrc 以确保 django 始终使用 local_settings.py

        export DJANGO_SETTINGS_MODULE=app.settings.local_settings
        

        编辑:

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

        【讨论】:

        • 这就是我正在为生产做的 settings_local.py 设置我不想提交到 git repo 的值。抱歉不准确。
        猜你喜欢
        • 1970-01-01
        • 2021-11-06
        • 1970-01-01
        • 1970-01-01
        • 2014-11-05
        • 2011-03-28
        • 1970-01-01
        • 2014-08-21
        • 1970-01-01
        相关资源
        最近更新 更多