Ruby-on-rails 如何解决错误“‘生产’环境缺少‘secret_key_base’”(Rails 4.1)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23180650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to solve error "Missing `secret_key_base` for 'production' environment" (Rails 4.1)
提问by Paolo Laurenti
I created a Rails application, using Rails 4.1, from scratch and I am facing a strange problem that I am not able to solve.
我使用 Rails 4.1 从头开始创建了一个 Rails 应用程序,但遇到了一个我无法解决的奇怪问题。
Every time I try to deploy my application on Heroku I get an error 500:
每次我尝试在 Heroku 上部署我的应用程序时,我都会收到错误 500:
Missing `secret_key_base` for 'production' environment, set this value in `config/secrets.yml`
The secret.ymlfile contains the following configuration:
该secret.yml文件包含以下配置:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
On Heroku I configured the "SECRET_KEY_BASE" environment variable with the result of the rake secretcommand. If I launch heroku config, I can see the variable with the correct name and value.
在 Heroku 上,我使用命令SECRET_KEY_BASE的结果配置了“ ”环境变量rake secret。如果我启动heroku config,我可以看到具有正确名称和值的变量。
Why am I still getting this error?
为什么我仍然收到此错误?
回答by Demi Magus
I had the same problem and solved it by creating an environment variable to be loaded every time I logged in to the production server, and made a mini-guideof the steps to configure it:
我遇到了同样的问题并通过创建一个每次登录生产服务器时加载的环境变量来解决它,并制作了配置它的步骤的迷你指南:
I was using Rails 4.1 with Unicorn v4.8.2 and when I tried to deploy my application it didn't start properly and in the unicorn.logfile I found this error message:
我在 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)
After some research I found out that Rails 4.1 changed the way to manage the secret_key, so if you read the secrets.ymlfile located at exampleRailsProject/config/secrets.ymlyou'll find something like this:
经过一番研究,我发现的Rails 4.1改变管理方式secret_key,所以如果你读了secrets.yml位于文件exampleRailsProject/config/secrets.yml,你会发现这样的事情:
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
This means that Rails recommends you to use an environment variable for the secret_key_basein your production server. In order to solve this error you should follow these steps to create an environment variable for Linux (in my case Ubuntu) in your production server:
这意味着 Rails 建议您secret_key_base在生产服务器中使用环境变量。为了解决这个错误,你应该按照以下步骤在你的生产服务器中为 Linux(在我的例子中是 Ubuntu)创建一个环境变量:
In the terminal of your production server execute:
$ RAILS_ENV=production rake secretThis returns a large string with letters and numbers. Copy that, which we will refer to that code as
GENERATED_CODE.Login to your server
If you login as the root user, find this file and edit it:
$ vi /etc/profileGo to the bottom of the file using Shift+G(capital "G") in vi.
Write your environment variable with the
GENERATED_CODE, pressing ito insert in vi. Be sure to be in a new line at the end of the file:$ export SECRET_KEY_BASE=GENERATED_CODESave the changes and close the file using Escand then "
:x" and Enterfor save and exit in vi.But if you login as normal user, let's call it "
example_user" for this gist, you will need to find one of these other files:$ vi ~/.bash_profile $ vi ~/.bash_login $ vi ~/.profileThese files are in order of importance, which means that if you have the first file, then you wouldn't need to edit the others. If you found these two files in your directory
~/.bash_profileand~/.profileyou only will have to write in the first one~/.bash_profile, because Linux will read only this one and the other will be ignored.Then we go to the bottom of the file using Shift+Gagain and write the environment variable with our
GENERATED_CODEusing iagain, and be sure add a new line at the end of the file:$ export SECRET_KEY_BASE=GENERATED_CODEHaving written the code, save the changes and close the file using Escagain and "
:x" and Enterto save and exit.
You can verify that our environment variable is properly set in Linux with this command:
$ printenv | grep SECRET_KEY_BASEor with:
$ echo $SECRET_KEY_BASEWhen you execute this command, if everything went ok, it will show you the
GENERATED_CODEfrom before. Finally with all the configuration done you should be able to deploy without problems your Rails application with Unicorn or some other tool.
在生产服务器的终端中执行:
$ 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再次与我们写的环境变量
GENERATED_CODE使用 i一次,并且一定要在文件的结尾添加新行:$ export SECRET_KEY_BASE=GENERATED_CODE编写代码后,Esc再次使用“
:x”和“ ”保存更改并关闭文件并Enter保存并退出。
您可以使用以下命令验证我们的环境变量是否在 Linux 中正确设置:
$ printenv | grep SECRET_KEY_BASE或与:
$ echo $SECRET_KEY_BASE当您执行此命令时,如果一切顺利,它将显示
GENERATED_CODE之前的内容。最后,完成所有配置后,您应该可以毫无问题地使用 Unicorn 或其他工具部署 Rails 应用程序。
When you close your shell and login again to the production server you will have this environment variable set and ready to use it.
当您关闭 shell 并再次登录到生产服务器时,您将设置此环境变量并准备好使用它。
And that's it! I hope this mini-guidehelps you solve this error.
就是这样!我希望这个迷你指南可以帮助您解决这个错误。
Disclaimer: I'm not a Linux or Rails guru, so if you find something wrong or any error I will be glad to fix it.
免责声明:我不是 Linux 或 Rails 专家,所以如果您发现有问题或任何错误,我很乐意修复它。
回答by Erik Trautman
I'm going to assume that you do not have your secrets.ymlchecked into source control (ie. it's in the .gitignorefile). Even if this isn't your situation, it's what many other people viewing this question have done because they have their code exposed on Github and don't want their secret key floating around.
我将假设您没有secrets.yml签入源代码管理(即它在.gitignore文件中)。即使这不是您的情况,这也是许多其他查看此问题的人所做的,因为他们在 Github 上公开了自己的代码,并且不希望他们的密钥四处流传。
If it's not in source control, Heroku doesn't know about it. So Rails is looking for Rails.application.secrets.secret_key_baseand it hasn't been set because Rails sets it by checking the secrets.ymlfile which doesn't exist. The simple workaround is to go into your config/environments/production.rbfile and add the following line:
如果它不在源代码管理中,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
This tells your application to set the secret key using the environment variable instead of looking for it in secrets.yml. It would have saved me a lot of time to know this up front.
这会告诉您的应用程序使用环境变量设置密钥,而不是在secrets.yml. 预先知道这一点会为我节省很多时间。
回答by danielricecodes
Add config/secrets.ymlto version control and deploy again. You might need to remove a line from .gitignoreso that you can commit the file.
添加config/secrets.yml到版本控制并再次部署。您可能需要从中删除一行,.gitignore以便提交文件。
I had this exact same issue and it just turned out that the boilerplate .gitignoreGithub created for my Rails application included config/secrets.yml.
我遇到了完全相同的问题,结果发现.gitignoreGithub 为我的 Rails 应用程序创建的样板文件包含config/secrets.yml.
回答by sumitsv21
This worked for me.
这对我有用。
SSH into your production server and cdinto your current directory, run bundle exec rake secretor rake secret, you will get a long string as an output, copy that string.
SSH 进入您的生产服务器并cd进入您的当前目录,运行bundle exec rake secret或rake secret,您将获得一个长字符串作为输出,复制该字符串。
Now run sudo nano /etc/environment.
现在运行sudo nano /etc/environment。
Paste at the bottom of the file
粘贴到文件底部
export SECRET_KEY_BASE=rake secret
ruby -e 'p ENV["SECRET_KEY_BASE"]'
Where rake secretis the string you just copied, paste that copied string in place of rake secret.
rake secret您刚刚复制的字符串在哪里,将复制的字符串粘贴到rake secret.
Restart the server and test by running echo $SECRET_KEY_BASE.
重新启动服务器并通过运行进行测试echo $SECRET_KEY_BASE。
回答by stackunderflow
While you can use initializers like the other answers, the conventional Rails 4.1+ way is to use the config/secrets.yml. The reason for the Rails team to introduce this is beyond the scope of this answer but the TL;DR is that secret_token.rbconflates configuration and code as well as being a security risk since the token is checked into source control history and the only system that needs to know the production secret token is the production infrastructure.
虽然您可以像其他答案一样使用初始化程序,但传统的 Rails 4.1+ 方法是使用config/secrets.yml. Rails 团队引入这一点的原因超出了本答案的范围,但 TL;DR 是secret_token.rb将配置和代码混为一谈,并且存在安全风险,因为令牌被检查到源代码控制历史记录中,并且是唯一需要知道生产秘密令牌是生产基础设施。
You should add this file to .gitignoremuch like you wouldn't add config/database.ymlto source control either.
您应该.gitignore像不添加config/database.yml到源代码管理一样添加此文件。
Referencing Heroku's own code for setting up config/database.ymlfrom DATABASE_URLin their Buildpack for Ruby, I ended up forking their repoand modified it to create config/secrets.ymlfrom SECRETS_KEY_BASEenvironment variable.
引用Heroku的自己的代码用于设置config/database.yml从DATABASE_URL他们的Buildpack为Ruby,我结束了分叉的回购和修改它来创建config/secrets.yml从SECRETS_KEY_BASE环境变量。
Since this feature was introduced in Rails 4.1, I felt it was appropriate to edit ./lib/language_pack/rails41.rband add this functionality.
由于这个功能是在 Rails 4.1 中引入的,我觉得编辑./lib/language_pack/rails41.rb和添加这个功能是合适的。
The following is the snippetfrom the modified buildpack I created at my company:
以下是我在公司创建的修改后的 buildpack的片段:
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
You can of course extend this code to add other secrets (e.g. third party API keys, etc.) to be read off of your environment variable:
您当然可以扩展此代码以添加其他机密(例如第三方 API 密钥等)以从您的环境变量中读取:
...
<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
third_party_api_key: <%= ENV["THIRD_PARTY_API"] %>
This way, you can access this secret in a very standard way:
这样,您可以以非常标准的方式访问此机密:
Rails.application.secrets.third_party_api_key
Before redeploying your app, be sure to set your environment variable first:

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

Then add your modified buildpack (or you're more than welcome to link to mine) to your Heroku app (see Heroku's documentation) and redeploy your app.
然后将您修改后的 buildpack(或者欢迎您链接到我的)到您的 Heroku 应用程序(请参阅 Heroku 的文档)并重新部署您的应用程序。
The buildpack will automatically create your config/secrets.ymlfrom your environment variable as part of the dyno build process every time you git pushto Heroku.
config/secrets.yml每次git push访问 Heroku时,作为 dyno 构建过程的一部分,buildpack 将自动从您的环境变量创建您的。
EDIT: Heroku's own documentationsuggests creating config/secrets.ymlto read from the environment variable but this implies you should check this file into source control. In my case, this doesn't work well since I have hardcoded secrets for development and testing environments that I'd rather not check in.
编辑:Heroku 自己的文档建议创建config/secrets.yml以从环境变量中读取,但这意味着您应该将此文件检查到源代码管理中。就我而言,这不太好用,因为我对开发和测试环境有硬编码的秘密,而我不想签入。
回答by alessandrocb
You can export the secret keys to as environment variables on the ~/.bashrcor ~/.bash_profileof your server:
您可以将密钥导出为服务器上的~/.bashrc或环境变量~/.bash_profile:
export SECRET_KEY_BASE = "YOUR_SECRET_KEY"
And then, you can source your .bashrcor .bash_profile:
然后,您可以获取您的.bashrcor .bash_profile:
source ~/.bashrc
source ~/.bash_profile
Never commit your secrets.yml
永远不要提交你的秘密.yml
回答by Andrew Koster
In my case, the problem was that config/master.keywas not in version control, and I had created the project on a different computer.
就我而言,问题出config/master.key在版本控制之外,我在另一台计算机上创建了该项目。
The default .gitignore that Rails creates excludes this file. Since it's impossible to deploy without having this file, it needs to be in version control, in order to be able to deploy from any team member's computer.
Rails 创建的默认 .gitignore 不包括这个文件。由于没有此文件就无法部署,因此需要进行版本控制,以便能够从任何团队成员的计算机进行部署。
Solution: remove the config/master.keyline from .gitignore, commit the file from the computer where the project was created, and now you can git pullon the other computer and deploy from it.
解决方案:config/master.key从 中删除行.gitignore,从创建项目的计算机提交文件,现在您可以git pull在另一台计算机上并从中部署。
People are saying not to commit some of these files to version control, without offering an alternative solution. As long as you're not working on an open source project, I see no reason not to commit everything that's required to run the project, including credentials.
人们说不要将其中一些文件提交给版本控制,而不提供替代解决方案。只要您不从事开源项目,我认为没有理由不提交运行项目所需的一切,包括凭据。
回答by Tushar H
For rails6, I was facing the same problem, as I was missing following files, once I added them, the issue resolved:
对于 rails6,我遇到了同样的问题,因为我缺少以下文件,一旦我添加了它们,问题就解决了:
1. config/master.key
2. config/credentials.yml.enc
Make sure you have this files.!!!
确保你有这个文件。!!!
回答by Geraud Puechaldou
What I did : On my production server, I create a config file (confthin.yml) for Thin (I'm using it) and add the following information :
我所做的:在我的生产服务器上,我为 Thin(我正在使用它)创建了一个配置文件 (confthin.yml) 并添加以下信息:
environment: production
user: www-data
group: www-data
SECRET_KEY_BASE: mysecretkeyproduction
I then launch the app with
然后我启动应用程序
thin start -C /whereeveristhefieonprod/configthin.yml
Work like a charm and then no need to have the secret key on version control
像魅力一样工作,然后不需要在版本控制上拥有密钥
Hope it could help, but I'm sure the same thing could be done with Unicorn and others.
希望它能有所帮助,但我相信 Unicorn 和其他人也可以做同样的事情。
回答by BF4
I have a patch that I've used in a Rails 4.1 app to let me continue using the legacy key generator (and hence backwards session compatibility with Rails 3), by allowing the secret_key_base to be blank.
我有一个在 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
I've since reformatted the patch are submitted it to Rails as a Pull Request
我已经重新格式化补丁将其作为拉取请求提交给 Rails

