如何解决“‘ production’环境缺少‘ secret _ key _ base’”错误(Rails 4.1)

我使用 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 上,我配置了“ SECRET_KEY_BASE”环境变量,使用的是 rake secret命令的结果。如果启动 heroku config,就可以看到具有正确名称和值的变量。

为什么我仍然得到这个错误?

181140 次浏览

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

我也遇到过同样的问题,结果是为我的 Rails 应用程序创建的样板 .gitignore Github 包含了 config/secrets.yml

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

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

然后启动应用程序

thin start -C /whereeveristhefieonprod/configthin.yml

像魔法一样工作,然后就不需要在版本控制上拥有秘密密钥

希望能有所帮助,但我相信同样的事情也可以在独角兽和其他人身上做到。

我在 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

我已经将补丁重新格式化为 作为拉动请求提交给 Rails

我也遇到过同样的问题,解决方法是创建一个环境变量,每次登录到生产服务器时都会加载它,然后制作一个配置步骤的 迷你导游:

我在 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) :

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

    $ RAILS_ENV=production rake secret
    

    这将返回一个包含字母和数字的大字符串。

  2. 登录到您的服务器

    • 如果您以 root 用户身份登录,找到这个文件并编辑它:

      $ vi /etc/profile
      

      使用 vi 中的 换挡 + G(大写“ G”)转到文件底部。

      用 abc0写环境变量,按 abc1插入 vi。一定要在文件末尾加上新的一行:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      保存更改并使用 埃斯克关闭文件,然后使用“ :x”和 进来在 vi 中保存和退出。

    • 但是,如果你作为普通用户登录,让我们把它称为“ example_user”为这个要点,你将需要找到这些其他文件之一:

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

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

      然后我们再次使用 换挡 + G到文件的底部,再次使用 用我们的 GENERATED_CODE写环境变量,并且确保在文件的末尾添加一行新的代码:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      编写完代码后,保存更改并再次使用 埃斯克和“ :x”和 进来关闭文件以保存和退出。

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

    $ printenv | grep SECRET_KEY_BASE
    

    或:

    $ echo $SECRET_KEY_BASE
    

    执行此命令时,如果一切正常,它将显示之前的 GENERATED_CODE。最后,在完成所有配置之后,您应该能够部署使用 Unicorn 或其他工具的 Rails 应用程序,而不会出现任何问题。

当你关闭 shell 并重新登录到生产服务器时,你就可以设置这个环境变量并准备使用它了。

就是这样! 我希望这个 迷你导游可以帮助您解决这个错误。

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

我将假设您没有将 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中查找。如果事先知道的话,我可以省很多时间。

我已经创建了 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:)

好好享受吧!

这招对我很管用。

SSH 到你的生产服务器,cd到你的工作目录,运行 bundle exec rake secret或者 rake 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重新启动服务器并进行测试。

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

在. gitignore 文件中注释了以下几行之后,一切都很顺利。

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

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

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

参考了 Heroku 自己的代码,在他们的 Ruby 的构建包中从 DATABASE_URL设置了 config/database.yml,我最终设置了 分发他们的回购协议,并修改了它,从 SECRETS_KEY_BASE环境变量创建了 config/secrets.yml

因为这个特性是在 Rails 4.1中引入的,所以我觉得编辑 ./lib/language_pack/rails41.rb并添加这个功能是合适的。

下面是我在公司创建的修改过的构建包中的 片段:

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

在重新部署应用程序之前,一定要先设置环境变量: Setting SECRET_KEY_BASE in Heroku Dashboard

然后将您修改过的 buildpack (或者您可以链接到我的)添加到 Heroku 应用程序(参见 Heroku 的 文件)并重新部署您的应用程序。

每次从你的环境变量到 Heroku,buildpack 都会自动创建你的 config/secrets.yml,作为 dyno 构建过程的一部分。

编辑: Heroku 自己的 文件建议创建从环境变量中读取的 config/secrets.yml,但这意味着你应该将这个文件检查到源代码控制中。在我的例子中,由于我有开发和测试环境的硬编码秘密,我宁愿不签入这些秘密,所以这种方法不能很好地工作。

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

$ /etc/profile

但是,如果您不是 root 用户,则应将生成代码放在以下位置

$ ~/.bash_profile


$ ~/.bash_login


$ ~/.profile

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

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

然后,你可以找到你的 .bashrc或者 .bash_profile:

source ~/.bashrc
source ~/.bash_profile

永远不要把你的秘密交给别人

在 Nginx/旅客/Ruby (2.4)/Rails (5.1.1)上,除了:

服务器块中 /etc/nginx/sites-available/default中的 passenger_env_var

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

在 Rails 5之前,半魔术师的答案一直为我所用。

在 Apache2/Customer/Ruby (2.4)/Rails (5.1.6)上,我必须将

export SECRET_KEY_BASE=GENERATED_CODE

来自 Demi Magus 的回答是/etc/apache2/envars,cause/etc/profile 似乎被忽略了。

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

在我的案例中,问题是 config/master.key不在版本控制中,而且我在另一台计算机上创建了该项目。

默认值。Rails 创建的 gitignore 将排除此文件。由于没有这个文件就不可能进行部署,因此它需要处于版本控制中,以便能够从任何团队成员的计算机进行部署。

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

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

对于 Rails6,我面临着与丢失下列文件相同的问题。一旦我把它们加进去,问题就解决了:

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

确保你有这些文件!