如何解决错误“‘生产’环境缺少‘secret_key_base’”(Rails 4.1)

Posted

技术标签:

【中文标题】如何解决错误“‘生产’环境缺少‘secret_key_base’”(Rails 4.1)【英文标题】:How to solve error "Missing `secret_key_base` for 'production' environment" (Rails 4.1) 【发布时间】:2014-06-04 12:42:03 【问题描述】:

我使用 Rails 4.1 从头开始​​创建了一个 Rails 应用程序,但遇到了一个我无法解决的奇怪问题。

每次我尝试在 Heroku 上部署我的应用程序时都会收到错误 500:

Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`

secret.yml 文件包含以下配置:

secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

在 Heroku 上,我使用 rake secret 命令的结果配置了“SECRET_KEY_BASE”环境变量。如果我启动heroku config,我可以看到具有正确名称和值的变量。

为什么我仍然收到此错误?

【问题讨论】:

我也遇到了同样的问题,也很想知道为什么会这样。如果我找出原因,我会回复我的解决方案。 你的配置文件是secret.yml还是secrets.yml 我用 rails 生成的文件再次配置了 .gitignore 文件,现在一切正常 我们在升级到 Rails 4 时也遇到了这个问题。在我们的例子中,这是因为我们有一个自定义环境名称,而这没有反映在 secrets.yml 中。我只需要用非标准名称在文件中添加一行,提交并重新部署。 对于未来的读者:这个答案可能是最简单和最准确的:***.com/a/26541742/4880924 【参考方案1】:

我遇到了同样的问题,通过创建一个环境变量来解决它,每次登录到生产服务器时都要加载,并做了一个mini-guide的配置步骤:

我使用的是带有 Unicorn v4.8.2 的 Rails 4.1,当我尝试部署我的应用程序时,它没有正常启动,在 unicorn.log 文件中我发现了以下错误消息:

app error: Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml` (RuntimeError)

经过一番研究,我发现 Rails 4.1 改变了管理secret_key 的方式,所以如果你阅读位于exampleRailsProject/config/secrets.ymlsecrets.yml 文件,你会发现如下内容:

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

这意味着 Rails 建议您在生产服务器中为 secret_key_base 使用环境变量。为了解决此错误,您应该按照以下步骤在生产服务器中为 Linux(在我的情况下为 Ubuntu)创建环境变量:

    在生产服务器的终端执行:

    $ RAILS_ENV=production rake secret
    

    这将返回一个包含字母和数字的大字符串。复制它,我们将该代码称为GENERATED_CODE

    登录您的服务器

    如果您以 root 用户身份登录,请找到此文件并对其进行编辑:

    $ vi /etc/profile
    

    在 vi 中使用 Shift+G(大写“G”)转到文件底部。

    GENERATED_CODE 写你的环境变量,按i 插入vi。确保在文件末尾换行:

    $ export SECRET_KEY_BASE=GENERATED_CODE
    

    使用 Esc 保存更改并关闭文件,然后使用 ":x" 和 Enter 保存并在 vi 中退出。

    但是,如果您以普通用户身份登录,我们将其命名为“example_user”作为此要点,您将需要找到以下其他文件之一:

    $ vi ~/.bash_profile
    $ vi ~/.bash_login
    $ vi ~/.profile
    

    这些文件按重要性排序,这意味着如果您拥有第一个文件,则无需编辑其他文件。如果您在目录~/.bash_profile~/.profile 中找到这两个文件,则只需写入第一个~/.bash_profile,因为Linux 将只读取这一个而忽略另一个。

    然后我们再次使用 Shift+G 转到文件底部,并使用 i 将我们的GENERATED_CODE 写入环境变量再次,并确保在文件末尾添加一个新行:

    $ export SECRET_KEY_BASE=GENERATED_CODE
    

    编写代码后,保存更改并再次使用 Esc 关闭文件,“:x”和 Enter 保存并退出。

    您可以使用以下命令验证我们的环境变量是否在 Linux 中正确设置:

    $ printenv | grep SECRET_KEY_BASE
    

    或与:

    $ echo $SECRET_KEY_BASE
    

    当你执行这个命令时,如果一切正常,它会显示你之前的GENERATED_CODE。最后,完成所有配置后,您应该能够使用 Unicorn 或其他工具毫无问题地部署 Rails 应用程序。

当您关闭 shell 并再次登录到生产服务器时,您将设置此环境变量并准备好使用它。

就是这样!我希望这个mini-guide 可以帮助你解决这个错误。

免责声明:我不是 Linux 或 Rails 专家,所以如果您发现有问题或任何错误,我将很乐意修复它。

【讨论】:

看来,Rails 没有看到环境变量 SECRET_KEY_BASE。 printenv 显示它,如果我检查 ENV,rails c production 也会显示它。但是,当我重新启动独角兽时,我没有任何效果。现在唯一可行的方法是将其直接粘贴到 secrets.yml 这对我有用。感谢您的完整解释。我刚刚了解到存在用于管理应用程序环境变量的 gem。 'Dotenv' 是 heroku 的一个和 '工头'。虽然以这种方式手动修复错误是一种教育,但也许使用其中一种宝石可以简化流程? 我很高兴我的回答很有帮助,感谢 gem 选项@ninja08,它们确实使过程更容易,主要是对于那些使用 capistrano 或其他增量工具来管理服务器的人 :) 按照 Demi Magus 的出色指导,我做了这样的事情:cd /var/www/rails; rvm 使用 ext-rbx-2.5.2@rails; SKB_FILE=/var/www/.secret_key_base; echo "export SECRET_KEY_BASE=$(RAILS_ENV=production rake secret)" > $SKB_FILE; . $SKB_FILE;回声“。$SKB_FILE”| tee -a ~/.bashrc ~/.bash_profile; chmod o-rwx $SKB_FILE; 很好的答案!我不知道为什么这不能为我解决,我创建了问题***.com/questions/33117318/…【参考方案2】:

我将假设您没有将您的secrets.yml 签入源代码控制(即它在.gitignore 文件中)。即使这不是您的情况,这也是许多查看此问题的其他人所做的,因为他们将代码暴露在 Github 上并且不希望他们的密钥四处飘荡。

如果它不在源代码管理中,Heroku 不知道它。所以 Rails 正在寻找 Rails.application.secrets.secret_key_base 并且它没有被设置,因为 Rails 通过检查不存在的 secrets.yml 文件来设置它。简单的解决方法是进入您的 config/environments/production.rb 文件并添加以下行:

Rails.application.configure do
    ...
    config.secret_key_base = ENV["SECRET_KEY_BASE"]
    ...
end

这告诉您的应用程序使用环境变量设置密钥,而不是在secrets.yml 中查找它。提前知道这一点会为我节省很多时间。

【讨论】:

这是最好的答案。 Figaroheroku_secrets 不做任何事情,除非 Rails 知道 SECRET_KEY_BASE 存在于 ENV 中。我一直在苦苦思索,如果配置变量存在于 Heroku 上,Rails 会因为它存在而选择它,但现在看起来很明显,Rails 需要知道去哪里看。我一直想知道如何在 Github 上拥有代码而不必担心密钥库的问题;现在我知道了。 同意,我认为 secrets.yml 对于像 Figaro 这样的伟大宝石是多余的。 如果您的项目使用 github 和 heroku,这似乎是最佳选择。 使用 production: secret_key_base: &lt;%= ENV["SECRET_KEY_BASE"] %&gt; 提交您的 secrets.yml 有什么问题。这是否也意味着实际的密钥没有公开。如果只是种子和测试数据,是否存在在已提交的 secrets.yml 中暴露开发和测试密钥的风险? 这在 Rails 6.0.2 中也有效,当没有 secrets.yml 时。【参考方案3】:

config/secrets.yml 添加到版本控制并再次部署。您可能需要从.gitignore 中删除一行,以便您可以提交文件。

我遇到了同样的问题,结果发现为我的 Rails 应用程序创建的样板文件 .gitignore Github 包括 config/secrets.yml

【讨论】:

config/secrets.yml 永远不应该在 repo 中,你可以做 .yml.sample 并用假数据填充它,但为了安全起见,永远不要在 repos 中做 .yml @user3379926,在 Heroku 上的 Rails 应用程序上下文中,您无法选择哪些文件包含在版本控制中,哪些不包含。 Rails 4.1 期望秘密配置存在,否则应用程序将无法运行。如果您有办法解决上述问题中提出的问题,而无需在 Git 中提交 secrets.yml 文件,请通过提供该建议来帮助改进此线程。 @danielricecodes 您可以在初始化程序中手动设置值。 Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"] 之类的东西可以工作并消除错误,而无需将 secrets.yml 添加到源中。 @user3379926:当我使用rails new 生成一个新的Rails 应用程序时(在这种情况下,生成一个Gemfile,其rails gem 的版本为4.2.4),文件config/secrets.yml 是生成。它包括用于开发和测试环境的预生成密钥,并从环境变量中读取生产环境的密钥:secret_key_base: &lt;%= ENV["SECRET_KEY_BASE"] %&gt;。在我看来,将这个secrets.yml 文件保存在版本控制中是非常安全且确实有用的,前提是从未真正定义那里的密钥。 @jasonleonhard 为什么?无论如何,如果您正在从 env vars 中读取密钥,那有什么大不了的?没有任何秘密被泄露。【参考方案4】:

这对我有用。

SSH 进入你的生产服务器,cd 进入你的当前目录,运行bundle exec rake secretrake secret,你会得到一个长字符串作为输出,复制那个字符串。

现在运行sudo nano /etc/environment

粘贴到文件底部

export SECRET_KEY_BASE=rake secret
ruby -e 'p ENV["SECRET_KEY_BASE"]'

rake secret 是您刚刚复制的字符串,将复制的字符串粘贴到 rake secret 的位置。

重启服务器并运行echo $SECRET_KEY_BASE进行测试。

【讨论】:

【参考方案5】:

虽然您可以像其他答案一样使用初始化程序,但传统的 Rails 4.1+ 方法是使用config/secrets.yml。 Rails 团队引入此内容的原因超出了此答案的范围,但 TL;DR 是 secret_token.rb 将配置和代码混为一谈,并且存在安全风险,因为令牌已检入源代码控制历史记录和唯一的系统需要知道生产秘密令牌的是生产基础设施。

您应该将此文件添加到 .gitignore,就像您不会将 config/database.yml 添加到源代码管理一样。

在他们的Buildpack for Ruby 中引用Heroku 自己的代码以从DATABASE_URL 设置config/database.yml,我最终得到forking their repo 并将其修改为从SECRETS_KEY_BASE 环境变量创建config/secrets.yml

由于这个功能是在 Rails 4.1 中引入的,我觉得编辑 ./lib/language_pack/rails41.rb 并添加这个功能是合适的。

以下是我在公司创建的修改后的 buildpack 中的snippet:

class LanguagePack::Rails41 < LanguagePack::Rails4

  # ...

  def compile
    instrument "rails41.compile" do
      super
      allow_git do
        create_secrets_yml
      end
    end
  end

  # ...

  # writes ERB based secrets.yml for Rails 4.1+
  def create_secrets_yml
    instrument 'ruby.create_secrets_yml' do
      log("create_secrets_yml") do
        return unless File.directory?("config")
        topic("Writing config/secrets.yml to read from SECRET_KEY_BASE")
        File.open("config/secrets.yml", "w") do |file|
          file.puts <<-SECRETS_YML
<%
raise "No RACK_ENV or RAILS_ENV found" unless ENV["RAILS_ENV"] || ENV["RACK_ENV"]
%>

<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
          SECRETS_YML
        end
      end
    end
  end

  # ...

end

您当然可以扩展此代码以添加其他机密(例如第三方 API 密钥等)以从您的环境变量中读取:

...
<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  third_party_api_key: <%= ENV["THIRD_PARTY_API"] %>

这样,您可以以非常标准的方式访问此密钥:

Rails.application.secrets.third_party_api_key

在重新部署您的应用之前,请务必先设置您的环境变量:

然后将修改后的 buildpack(或者非常欢迎您链接到我的)添加到您的 Heroku 应用(请参阅 Heroku 的 documentation)并重新部署您的应用。

每次您将 git push 发送到 Heroku 时,作为 dyno 构建过程的一部分,buildpack 都会自动从您的环境变量创建您的 config/secrets.yml

编辑:Heroku 自己的documentation 建议创建config/secrets.yml 以从环境变量中读取,但这意味着您应该将此文件签入源代码管理。就我而言,这并不好用,因为我对开发和测试环境的秘密进行了硬编码,我不想签入。

【讨论】:

虽然 .dotenv 和 .foreman gems 是一个很好的解决方案,但它解决了这个问题:“我有用于开发和测试环境的硬编码秘密”——所以使用这些 gems 意味着你不需要 buildpack,因为你可以使用ENV_VAR 在您的秘密文件中用于开发和测试 请注意,大多数基础设施都会记录环境变量,这意味着未加密的环境变量将在日志中以纯文本形式出现。我不将 Heroku 用于我的 Rails 应用程序,因此不建议使用它,但使用 AWS,我们在构建期间从构建容器内部从 Parameter Store 中提取加密值,并对其解密以填充这些类型的安全资产。【参考方案6】:

您可以将密钥导出为服务器的~/.bashrc~/.bash_profile 上的环境变量:

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

然后,您可以获取您的 .bashrc.bash_profile

source ~/.bashrc 
source ~/.bash_profile

永远不要提交你的 secrets.yml

【讨论】:

【参考方案7】:

对于 rails6,我遇到了同样的问题,因为我缺少以下文件。一旦我添加了它们,问题就解决了:

1. config/master.key
2. config/credentials.yml.enc

确保您拥有这些文件!

【讨论】:

【参考方案8】:

我做了什么: 在我的生产服务器上,我为 Thin 创建了一个配置文件 (confthin.yml)(我正在使用它)并添加以下信息:

environment: production
user: www-data
group: www-data
SECRET_KEY_BASE: mysecretkeyproduction

然后我使用

启动应用程序
thin start -C /whereeveristhefieonprod/configthin.yml

像魅力一样工作,然后不需要在版本控制上拥有密钥

希望它能有所帮助,但我相信 Unicorn 和其他人也可以这样做。

【讨论】:

你能解释一下为什么/如何工作吗?这个问题是针对heroku的。瘦是替代品,还是与heroku兼容?【参考方案9】:

就我而言,问题在于config/master.key 不在版本控制中,我在另一台计算机上创建了项目。

Rails 创建的默认 .gitignore 不包括该文件。由于没有此文件就无法部署,因此需要对其进行版本控制,以便能够从任何团队成员的计算机进行部署。

解决方案:从.gitignore 中删除config/master.key 行,从创建项目的计算机上提交文件,现在您可以在另一台计算机上git pull 并从中进行部署。

人们说不要在不提供替代解决方案的情况下将其中一些文件提交给版本控制。只要您不从事开源项目,我认为没有理由不提交运行该项目所需的所有内容,包括凭据。

【讨论】:

永远不要将你的主密钥文件提交给 git。对于您的应用来说,这是一个巨大的安全漏洞。对于开源来说,这很困难,但使用您喜欢的密码管理器创建密码库是更好的选择。 您在生产环境中设置了RAILS_MASTER_KEY 环境变量。您的回答非常错误(根据 Rails 文档)并导致不安全的情况。请更新或删除它。 @RobinDaugherty 请详细说明。什么是“不安全条件”,我们应该如何避免? 就像@wsizoo。将主密钥提交给版本控制是不安全的,不应该这样做。它在.gitignore 文件中是有充分理由的。通过其他方式共享文件以进行开发。遵循 12-factor-app 原则并将其置于生产环境中。 特别是对于开源项目,生产中的主密钥不应该与世界共享。【参考方案10】:

我有一个在 Rails 4.1 应用程序中使用过的补丁,通过允许 secret_key_base 为空,我可以继续使用旧版密钥生成器(因此向后兼容 Rails 3)。

Rails::Application.class_eval do
  # the key_generator will then use ActiveSupport::LegacyKeyGenerator.new(config.secret_token)
  fail "I'm sorry, Dave, there's no :validate_secret_key_config!" unless instance_method(:validate_secret_key_config!)
  def validate_secret_key_config! #:nodoc:
    config.secret_token = secrets.secret_token
    if config.secret_token.blank?
      raise "Missing `secret_token` for '#Rails.env' environment, set this value in `config/secrets.yml`"
    end 
  end 
end

我已经重新格式化了补丁是submitted it to Rails as a Pull Request

【讨论】:

【参考方案11】:

我创建了config/initializers/secret_key.rb 文件,并且只编写了以下代码行:

Rails.application.config.secret_key_base = ENV["SECRET_KEY_BASE"]

但我认为@Erik Trautman 发布的解决方案更优雅;)

编辑: 哦,最后我在 Heroku 上找到了这个建议:https://devcenter.heroku.com/changelog-items/426 :)

享受吧!

【讨论】:

【参考方案12】:

这很好用https://gist.github.com/pablosalgadom/4d75f30517edc6230a67 对于 root 用户应该编辑

$ /etc/profile

但是如果你不是root应该把生成代码放在下面

$ ~/.bash_profile

$ ~/.bash_login

$ ~/.profile

【讨论】:

【参考方案13】:

nginx/Passenger/Ruby (2.4)/Rails (5.1.1) 上没有其他工作除了:

passenger_env_var in /etc/nginx/sites-available/default 在服务器块中。

来源:https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_env_var

【讨论】:

【参考方案14】:

Demi Magus 的答案在 Rails 5 之前对我有用。

在 Apache2/Passenger/Ruby (2.4)/Rails (5.1.6) 上,我不得不放

export SECRET_KEY_BASE=GENERATED_CODE

来自 /etc/apache2/envvars 中的 Demi Magus 回答,导致 /etc/profile 似乎被忽略了。

来源:https://www.phusionpassenger.com/library/indepth/environment_variables.html#apache

【讨论】:

【参考方案15】:

我在使用https://github.com/github/gitignore/blob/master/Rails.gitignore的.gitignore 文件后遇到了同样的问题

我在 .gitignore 文件中注释了以下几行后,一切正常。

config/initializers/secret_token.rb
config/secrets.yml

【讨论】:

正如到处重复的那样,不建议将 secrets.yml 或 secret_token.rb 提交给 git。

以上是关于如何解决错误“‘生产’环境缺少‘secret_key_base’”(Rails 4.1)的主要内容,如果未能解决你的问题,请参考以下文章

"SQL SERVER,错误:207" 如何解决

如何解决“错误:输入中的语法错误(1)。”

如何解决此分段错误:以下代码的 11 错误?

如何解决子重复错误?

Ftp 错误代码 550,如何解决

这是啥覆盖错误,我该如何解决? [复制]