Rails 5.2 credentials.yaml.enc与master.key在Heroku上失效排查
看起来你遇到的核心问题是Rails在Heroku生产环境下无法从credentials.yaml.enc中正确读取S3的凭证信息,但直接通过Heroku环境变量配置就能正常运行——这说明AWS SDK本身是能正常工作的,问题出在Rails的凭证加载流程上。我帮你梳理几个最可能的原因和验证步骤:
1. 检查credentials.yaml.enc的结构是否正确
这是最常见的出错点:你的S3凭证必须嵌套在:amazon节点下,和storage.yml中配置的服务名对应。
正确的凭证结构应该是这样的(解密后内容):
amazon: access_key_id: YOUR_S3_ACCESS_KEY secret_access_key: YOUR_S3_SECRET_KEY bucket: YOUR_BUCKET_NAME region: YOUR_REGION(比如us-east-1)
如果你的凭证是直接放在根节点(没有嵌套在:amazon下),那么Rails.application.credentials.amazon[:access_key_id]就会返回nil,自然触发凭证缺失的错误。
2. 验证storage.yml的配置是否匹配凭证结构
确保storage.yml里的:amazon服务是从Rails凭证中读取值,而不是硬编码或读取其他来源:
# config/storage.yml amazon: service: S3 access_key_id: <%= Rails.application.credentials.amazon[:access_key_id] %> secret_access_key: <%= Rails.application.credentials.amazon[:secret_access_key] %> bucket: <%= Rails.application.credentials.amazon[:bucket] %> region: <%= Rails.application.credentials.amazon[:region] %>
同时要确认这个文件已经被提交到Git仓库并推送到Heroku——如果storage.yml没被部署,Heroku根本不知道要读取哪个凭证。
3. 确认Heroku的RAILS_MASTER_KEY完全匹配本地master.key
Heroku需要用RAILS_MASTER_KEY来解密credentials.yaml.enc,如果这个值和本地config/master.key的内容不一致,Heroku就无法解密凭证文件,自然读不到任何值。
你可以本地执行cat config/master.key,然后对比Heroku上的环境变量值:
heroku config:get RAILS_MASTER_KEY
确保两者完全相同(注意不要有多余的空格或换行)。
4. 本地生产环境验证凭证读取
在本地模拟生产环境,验证凭证是否能正常读取:
RAILS_ENV=production rails console
然后在控制台输入:
Rails.application.credentials.amazon
如果返回nil或者缺失某个字段,说明本地的凭证文件本身就有问题,和Heroku无关,先把本地的凭证配置修正。
为什么直接设Heroku环境变量能正常运行?
AWS的SDK会自动读取环境变量中的AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,这时候它绕过了Rails的凭证系统,直接从环境变量获取凭证,所以能正常工作。但这只是临时 workaround,还是要让Rails的凭证系统正常工作才是规范的做法。
内容的提问来源于stack exchange,提问作者spitz

