Railsアプリを本番デプロイしたらsecret_key_baseが未定義っておこられたので、どういう扱いになってるのか確認してみた。
確認したRailsのバージョンは6.0.0.rc1。
確認したRailsのバージョンは6.0.0.rc1。
はじめにまとめ
secret_key_baseの設定場所は4箇所ある:
- 環境変数:
ENV["SECRET_KEY_BASE"]
- credencials:
config/credentials.yml.enc
- secrets:
config/secrets.yml
(Encrypted secretsが有効ならconfig/secrets.yml.enc
) tmp/development_secret.txt
環境ごとの評価順:
- developmentかtestなら、secrets、
tmp/development_secret.txt
の順 - それ以外の環境なら、環境変数、credencials、secretsの順
secret_key_baseの取得
Rails.applicatin.secret_key_base #=> "bb7a320962dda4262e21262f80229946f5a3b3c05cc8968d71d1ae9e40c64b5d7afb5340c196134089590b69d8a51a05ee801217b90eb859236bf4b14f8d5a76"
secret_key_baseの定義場所
Rails::Application
にメソッドとして定義されている。railties/lib/rails/application.rb
module Rails # snip class Application < Engine # snip def secret_key_base if Rails.env.development? || Rails.env.test? secrets.secret_key_base ||= generate_development_secret else validate_secret_key_base( ENV["SECRET_KEY_BASE"] || credentials.secret_key_base || secrets.secret_key_base ) end end end end
- 環境がdevelopmentかtestの場合
-
secrets.secret_key_base
が未設定なら、generate_development_secret
を実行し結果をsecrets.secret_key_base
に保存する -
secrets.secret_key_base
を返す
-
- それ以外の場合
-
ENV["SECRET_KEY_BASE"]
、credentials.secret_key_base
、secrets.secret_key_base
の順番で評価してバリデーションした上で結果を返す
-
secrets.secret_key_baseとは
Rails::Application#secrets
が定義されてる。railties/lib/rails/application.rb
def secrets @secrets ||= begin secrets = ActiveSupport::OrderedOptions.new files = config.paths["config/secrets"].existent files = files.reject { |path| path.end_with?(".enc") } unless config.read_encrypted_secrets secrets.merge! Rails::Secrets.parse(files, env: Rails.env) # Fallback to config.secret_key_base if secrets.secret_key_base isn't set secrets.secret_key_base ||= config.secret_key_base secrets end end
-
config/secrets.yml
を読み込む - Rails 5.1で導入されたEncrypted secretsが有効なら
config/secrets.yml.enc
を読み込む -
config/secrets.yml
にsecret_key_baseが未定義ならconfig
から読み込む
config/secrets.yml
はRails 4.1で導入されたようなので、それ以前はconfig/application.rb
とかに書いてたのかな?https://guides.rubyonrails.org/4_1_release_notes.html#config-secrets-yml
generate_development_secretとは
railties/lib/rails/application.rb
def generate_development_secret if secrets.secret_key_base.nil? key_file = Rails.root.join("tmp/development_secret.txt") if !File.exist?(key_file) random_key = SecureRandom.hex(64) FileUtils.mkdir_p(key_file.dirname) File.binwrite(key_file, random_key) end secrets.secret_key_base = File.binread(key_file) end secrets.secret_key_base end
secret_key_baseが未設定なら
tmp/development_secret.txt
を自動生成してその内容を返すらしい。へー。まとめ
- 開発中はsecret_key_baseが自動生成されるので未設定で良さそう
- 本番環境は環境変数、credencials、secretsなど適切な方法で設定しておく