如何解决错误“缺少'secret_key_base`为'生产'环境”(Rails 4.1)

时间:2014-04-20 09:38:57

标签: ruby-on-rails ruby heroku ruby-on-rails-4

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

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

  

缺少secret_key_base生产'环境,在config/secrets.yml

中设置此值

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

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

在Heroku上我已经配置了一个环境变量&#34; SECRET_KEY_BASE&#34;结果&#34; rake secret&#34;命令。如果我启动&#34; heroku config&#34;,我可以看到具有正确名称和值的变量。

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

非常感谢

15 个答案:

答案 0 :(得分:196)

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

https://gist.github.com/pablosalgadom/4d75f30517edc6230a67

我在使用Rails 4.1和Unicorn v4.8.2时,当我尝试部署我的应用程序时,它没有正确启动,并且在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.yml的secrets.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
    

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

  2. 登录您的服务器

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

      $ vi /etc/profile
      

      转到文件底部(&#34; SHIFT + G&#34; VI中的大写字母G)

      使用GENERATED_CODE编写环境变量(按&#34; i&#34;键在VI中写入),请确保在文件末尾的新行中:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      保存更改并关闭文件(我们按&#34; ESC&#34;键然后写&#34;:x&#34;和&#34; ENTER&#34;键用于保存并退出VI )。

    • 但如果您以普通用户身份登录,请调用它&#34; example_user&#34;对于这个要点,你需要找到其他一个文件:

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

      这些文件按重要性排序,这意味着如果你有第一个文件,那么你就不需要写其他文件了。因此,如果您在目录~/.bash_profile~/.profile中找到这2个文件,则只需要在第一个~/.bash_profile中写入,因为Linux只读取此文件而另一个将被忽略

      然后我们转到文件的底部(&#34; SHIFT + G&#34;对于VI中的大写字母G)。

      我们将使用GENERATED_CODE编写环境变量(按&#34; i&#34;键在VI中写入),请确保在文件末尾的新行中:

      $ export SECRET_KEY_BASE=GENERATED_CODE
      

      编写代码后,保存更改并关闭文件(我们按&#34; ESC&#34;键然后写&#34;:x&#34;和&#34; ENTER&#34;键保存并退出VI)。

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

    $ printenv | grep SECRET_KEY_BASE
    

    或与:

    $ echo $SECRET_KEY_BASE
    

    执行此命令时,如果一切正常,它将显示之前的GENERATED_CODE。最后,在完成所有配置后,您应该可以使用Unicorn或其他方式部署没有问题的Rails应用程序。

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

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

    免责声明:我不是Linux或Rails大师,所以如果您发现错误或任何错误,我将很乐意解决它!

答案 1 :(得分:81)

我将假设您没有secrets.yml检入源代码管理(即.gitignore文件中的Rails.application.secrets.secret_key_base。即使这不是你的情况,也是许多观看这个问题的人所做的事情,因为他们的代码暴露在Github上并且不希望他们的密钥浮动。

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

secrets.yml

这告诉您的应用程序使用环境变量设置密钥,而不是在{{1}}中查找它。这样可以节省我很多时间来预先知道这一点。

答案 2 :(得分:56)

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

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

答案 3 :(得分:13)

这对我有用。

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进行测试。

答案 4 :(得分:4)

虽然您可以像其他答案一样使用初始化程序,但传统的Rails 4.1+方法是使用config/secrets.yml。 Rails团队引入这个的原因超出了这个答案的范围,但是TL; DR是secret_token.rb将配置和代码混为一谈以及存在安全风险,因为令牌被检入源控制历史记录和只有需要了解生产密钥令牌的系统才是生产基础架构。

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

引用Heroku自己的代码,在Buildpack for Rubyconfig/database.yml设置DATABASE_URL,我最终forking their repo并将其修改为config/secrets.yml来自{{} 1}}环境变量。

由于Rails 4.1中引入了此功能,我认为编辑SECRETS_KEY_BASE并添加此功能是合适的。

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

./lib/language_pack/rails41.rb

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

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

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

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

在重新部署应用之前,请务必先设置环境变量: Setting SECRET_KEY_BASE in Heroku Dashboard

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

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

编辑:Heroku自己的documentation建议创建git push以从环境变量中读取,但这意味着您应该将此文件检入源代码管理中。在我的情况下,这不能很好地工作,因为我有开发和测试环境的硬编码秘密,我宁愿不签到。

答案 5 :(得分:2)

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

export SECRET_KEY_BASE = "YOUR_SECRET_KEY"

然后,您可以来源.bashrc.bash_profile

source ~/.bashrc 
source ~/.bash_profile

永远不要提交你的秘密。

答案 6 :(得分:2)

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

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

确保您具有此文件。!!!

答案 7 :(得分:1)

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

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

然后我用

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

像魅力一样工作,然后无需在版本控制上使用密钥

希望它能提供帮助,但我确信Unicorn和其他人可以做同样的事情。

答案 8 :(得分:0)

我有一个我在Rails 4.1应用程序中使用的补丁,让我继续使用遗留密钥生成器(因此与Rails 3的向后会话兼容性),允许secret_key_base为空。

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

答案 9 :(得分:0)

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

享受!

答案 10 :(得分:0)

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

$ /etc/profile

但如果您是非root用户,请将生成代码放在以下

$ ~/.bash_profile

$ ~/.bash_login

$ ~/.profile

答案 11 :(得分:0)

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

服务器块中passenger_env_var中的

/etc/nginx/sites-available/default

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

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

Rails创建的默认.gitignore排除了此文件。由于没有此文件就无法部署,因此它必须处于版本控制中,以便能够从任何团队成员的计算机进行部署。

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

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

答案 14 :(得分:-3)

使用https://github.com/github/gitignore/blob/master/Rails.gitignore

中的.gitignore文件后,我遇到了同样的问题

在我评论.gitignore文件中的以下行后,一切都很顺利。

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