Using Rails config_for as a replacement for secrets alongside credentials


Rails 5.1 introduced the use of secrets for storing encrypted secrets in source control.

It also allowed plain environment specific settings storage making usage of secrets.yml.

 # config/secrets.yml
 shared:
   mailer_default_from_email: "'Example' <notifications@example.com>"
   support_email: support@example.com
   mailer_delivery_method: :smtp
   mailer:
     smtp_settings:
       user_name: <%= ENV['AWS_SES_USERNAME'] %>
       password: <%= ENV['AWS_SES_PASSWORD'] %>
       address: email-smtp.us-east-1.amazonaws.com
       port: 587
       authentication: plain

 test:
   mailer_delivery_method: :test

 

And access this configuration using Rails.application.secrets

 Rails.application.secrets.mailer_default_from_email
 Rails.application.secrets.support_email
 Rails.application.secrets.mailer.smtp_settings # hash of smtp_settings configuration
 

Rails made use of SECRET_BASE_KEY for these encrypting the stored secrets.

The combination of config/secrets.yml, config/secrets.yml.enc, and SECRET_BASE_KEY was confusing. It was not clear what one should be putting in these secrets, encrypted secrets and how SECRET_BASE_KEY is related to the setup in general.

To overcome this confusion secrets were replaced with credentials, and limited its usage to only encrypted credentials/ Using secrets is now deprecated.

Using config_for as a replacement for secrets.yml

Since secrets.yml is now deprecate we need a new way to store the configuration above. We can make use of exiting functionality config_for to achieve same desired effects.

First, we break down and move the configuration to a new config file. Since the configuration is about mailer, lets store the config config/mailer.yml

 # config/mailer.yml
 shared:
   default_from_email: "'Example' <notifications@example.com>"
   support_email: support@example.com
   delivery_method: :smtp
   smtp_settings:
     user_name: <%= ENV['AWS_SES_USERNAME'] %>
     password: <%= ENV['AWS_SES_PASSWORD'] %>
     address: email-smtp.us-east-1.amazonaws.com
     port: 587
     authentication: plain
 test:
   delivery_method: :test

 

We need to then load this configuration.

# config/application.rb
module MyApplication
  class Application < Rails::Application
    
    # Config settings
    config.mailer = config_for(:mailer)
  end
end

After loading this configuration we can start using the mailer configuration on Rails.configuration.mailer

 Rails.configuration.mailer.default_from_email
 Rails.configuration.mailer.support_email
 Rails.configuration.mailer.smtp_settings # hash of smtp_settings configuration
 

Using config_for helps us break down configuration into separate namespaced files, relative to what they useful for: mailer, host, exception_notifier and more.