虽然您可以像其他答案一样使用初始化程序,但传统的 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 以从环境变量中读取,但这意味着您应该将此文件签入源代码管理。就我而言,这并不好用,因为我对开发和测试环境的秘密进行了硬编码,我不想签入。