The Marriage of Figaro… and Rails

Two years ago and 264,309 downloads ago, I wrote the Figaro gem. I had been using the pattern for some time already and was frustrated that something so simple wasn't already included in Rails. And now, finally, it is! Well… sort of.

Secrets

In the wee hours of this morning, DHH shipped Rails 4.1.0.beta1 with support for a config/secrets.yml file, which is strikingly similar to Figaro's config/application.yml in its function.

For those of you who are unfamiliar, Figaro loads the contents of application.yml and merges the values into ENV. The purpose is to provide Git-ignored configuration for sensitive information like API keys and other secrets.

# config/application.yml
stripe_publishable_key: pk_test_TLr0qqdKhm0yX1bZtKC4kFAC
stripe_secret_key: sk_test_Qbppb2nkFEzPoquOdBym0JL2

# config/initializers/stripe.rb
Stripe.api_key = ENV["stripe_secret_key"]

The purpose of the new secrets.yml file is the same: to keep sensitive configuration information out of source control. Plus, the implementation is similar.

# config/secrets.yml
stripe_publishable_key: pk_test_TLr0qqdKhm0yX1bZtKC4kFAC
stripe_secret_key: sk_test_Qbppb2nkFEzPoquOdBym0JL2

# config/initializers/stripe.rb
Stripe.api_key = Rails.application.secrets.stripe_secret_key

What now?

On the surface, this Rails feature looks like a Figaro-killer! Figaro even received a new GitHub issue within hours of the Rails release:

This is definitely a step in the right direction but it makes me sad for Figaro :(

However, there are some notable differences between the two approaches. Rails' secrets.yml has pros and cons when compared to Figaro's application.yml:

Pros

  1. Convention. Now that there's an agreed upon convention in the Rails community, there can be a familiarity amongst developers as to how to properly configure a Rails application. Plus, services like Heroku and Travis have the opportunity to support the new convention.
  2. Rich object support. ENV is limited to string key-value pairs. Oftentimes, an application needs configuration for a number of days or a fee percentage. These numeric values must be cast to strings when written and re-cast when read.
  3. Secure defaults. Now that Rails has a way to store sensitive information, newly generated applications will not check the secret\_key\_base into source control. Knowledge of the secret\_key\_base allows an attacker to read and manipulate an application's cookies, exposing your application to remote code execution. Revealing the secret\_key\_base value can be absolutely devastating.

Cons

  1. The Twelve-Factor App. The twelve-factor methodology outlines best practices for application development in twelve areas, and arises from the experience of prominent application developers and maintainers working on the Heroku platform. One of the twelve areas is Config. It's a great read! tl;dr: Use ENV.
  2. Deployment. Because secrets.yml doesn't use ENV, configuring your production application requires installing secrets.yml remotely for every application server. This doesn't play well with Heroku's existing configuration conventions using, you guessed it… ENV.

Conclusion

I don't believe that Rails 4.1's secrets.yml is a perfect solution for application configuration, but it is a fantastic start!

When I started to write Figaro two years ago, it was as a pull request to Rails. So don't be sad for Figaro! I'm very happy to see that a variation on Figaro finally made its way into Rails.

That said, there may still be a place for Figaro and I'd love to hear your thoughts here on what Figaro's future might look like.

UPDATE:

Add another con to the list. As of now, Rails does not Git-ignore secrets.yml by default. Going through the motions of generating a new Rails application will still commit the sensitive secret\_key\_base value to source control. I expect that this will be resolved before Rails 4.1.0 is released.


Check out our latest product, Dead Man’s Snitch for monitoring cron, heroku scheduler or any periodic task.

Dead Man's Snitch

steve@collectiveidea.com

Comments

  1. December 18, 2013 at 17:49 PM

    Take into account, however, that config/secrets.yml as other YAML files in Rails is passed first through ERB, so you can indeed use ENV.

  2. December 18, 2013 at 20:59 PM

    I’ll keep using Figaro or similar instead of the insecure-by-default setup on Rails. https://github.com/rails/rails/pull/13388

  3. steve@collectiveidea.com
    Steve Richert
    December 18, 2013 at 21:11 PM

    Alex: wow. I just assumed. I added an update to the post. Thank you!

  4. December 18, 2013 at 21:53 PM

    Thanks for the post! I have never used Figaro in an application before (mainly because I have never heard of the gem), but since I use Heroku for my main application, I am definitely going to be looking into this!

  5. December 18, 2013 at 22:05 PM

    The figaro gem is such a nice implementation. Thank you for conceiving it, building it, and maintaining it. It’s convenient to just “$ rake figaro:heroku” to set ENV variables when deploying on Heroku. But I guess If I can use ENV variables in the secrets.yml file, that’s good enough, and I’ll go back to setting ENV variables manually on Heroku. Unless there’s another benefit I’m overlooking?

  6. April 10, 2014 at 15:08 PM

    With the release of 4.1, what’s the verdict on it git-ignoring `config/secrets.yml` by default?

  7. steve@collectiveidea.com
    Steve Richert
    April 10, 2014 at 18:34 PM

    Dennis, great question! I just generated a new Rails 4.1 application and secrets.yml is not git-ignored. The Rails gods have wised up a bit in deciding that at least the production keys should be specified via ENV rather than in the file itself. My question is: why just in production?

    Here’s the generator template for secrets.yml:
    https://github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/templates/config/secrets.yml

    For now, Figaro lives on! Version 1.0 will be released shortly.
    https://github.com/laserlemon/figaro/blob/master/CHANGELOG.md

  8. October 09, 2014 at 5:43 AM

    Long live the Figaro!

  9. February 21, 2015 at 15:55 PM

    Just a quick post to say thanks for providing this! so much easier to use a simple gem than have to putz with heroku’s environment variables manually :-) (and for whatever reason just feels less secure)
    Now just for a simple way to do something like this for my certificate files….