Using Rails secrets.yml

July 31, 2015

One of the things I struggled with when I was starting to push my projects to a production environment was where and how do I put sensitive things like passwords, API keys or other things relating to the production specific environment. There are a number of gems to handle this for me but I wanted to look closer to see if I could find one in Rails.

Chris over at GoRails pointed me to the built-in secrets.yml inside of every config directory in the rails applications since Rails 4.1.

A new application only has one thing in that, being the secret_key_base. I completely overlooked the file and did not realize I could add my own to it.. Once I realized I could it's made sense.

For example, I needed to add Sendgrid to my website's application so that my Contact form would send emails. In development I used Environment Variables, but in production where sometimes I have multiple apps using the same services I would have to program them to be like APPNAME_SERVICE_APIKEY or something and then reference that in the code where the password/information is needed.

So inside my config/environments/development.rb file:

  config.action_mailer.smtp_settings = {
     :address        => 'smtp.sendgrid.net',
     :port           => '587',
     :authentication => :plain,
     :user_name      => ENV['ANDREWFOMERA_SENDGRID_USERNAME'],
     :password       => ENV['ANDREWFOMERA_SENDGRID_PASSWORD'],
     :domain         => 'sendgrid.example.com',
     :enable_starttls_auto => true
   }

There's a better way to handle this instead of worrying about ENV I decided to use secrets. Here's my production code:

  config.action_mailer.smtp_settings = {
     :address        => 'smtp.sendgrid.net',
     :port           => '587',
     :authentication => :plain,
     :user_name      => Rails.application.secrets.sendgrid_username,
     :password       => Rails.application.secrets.sendgrid_password,
     :domain         => 'sendgrid.example.com',
     :enable_starttls_auto => true
   }

It's a minor change, but by using Rails.application.secrets.key_name I'm able to keep all my keys/information in one file. NOTE: I do not commit the secrets.yml file to my repositories.

It's very important if you do this method you include secrets.yml in your .gitignore file. When you're ready to deploy your application and you make changes to the secrets.yml you just login to your server and add the keys to the secrets.yml file on the server. Here's what an example secrets.yml file would look like for the production section.

production:
  secret_key_base: 998bc1ec2e62e61bacde52f19813eab0af270f14ac59d9afdc275bf2b8f8c70a41090a061df042b266bada8fdb447443dee8ffa20a9289b13664d2edaf1ded7e
  sendgrid_username: myusernameisawesome
  sendgrid_password: herptyderpderpteherppassword

Don't worry, thats not my actual secret_key_base, I ran rake secret and generated a special one.

That's all you have to do to use secrets.yml. I'm somewhat lazy and like having things in files. Great for small one off apps, use environment variables for big time apps.

Hopefully this shed some light, you could choose just to use the secrets.yml file in development if you chose to, just make sure you reference it with something like

Rails.application.secrets.my_api_key

in your code where you need it. The process is the same for all of the environments.

Have fun developing! ~ Andrew