How can I store application secrets without keeping them in my source code?

I’m using AWS and I need to store my credentials securely. I’ve heard that I should store them in the environment which is something to do with the program that’s running. I’ve also tried putting it in an initialiser but couldn’t figure out how to access it from my controllers.

When you have important secrets that your application needs, the golden rule is do not store them in your source code. The reason for this is simple, if you give someone (say that new junior developer on a four week trial) access to your repository, suddenly they have access to your production servers and all the data that’s on there.

What secrets does your app contain?

Rails’ inbuilt secrets

Rails itself has a secrets.yml file that it stores in the config folder. This has a token, called “secret_key_base” that Rails uses to sign its cookies (making sure that a malicious client can’t tamper with them).

There’s also your database.yml file which stores the access credentials to your database. This is probably the single most important secret of the lot – if someone gets access to your database you’re in real trouble.

Config files

In addition, I often use the Paperclip gem, with AWS, so I tend to create a file called storage.yml, also in config, for storing those credentials.

None of these files should be stored in your repository – edit your .gitignore file
and add /config/*.yml as one of the first steps when setting up a new project.

I tend to copy the yml files and create an equivalent .example file (database.yml.example, storage.yml.example and so on), fill them with dummy values and check those into the repository – just to show people what’s needed to get this project deployed.

Deployment

So how do you get these files into the right place on your production server if they’re not in your repository?

If you use Capistrano to deploy, you can specify that some files should be sym-linked from Capistrano’s shared folder.

For example, somewhere in your config/deploy.rb add the following lines:

Then copy them by hand into the Capistrano shared/config folder and next time you deploy, it will automatically build the symlinks from your master files to the current deployment directory.

But, while Rails knows exactly what to do with secrets.yml and database.yml, for your own files you still need to load the credentials into your application.

Loading the data

Rails initialisers are perfect for this.

For my Paperclip configurations I create a file called config/intializers/storage.rb (I try to make the initialiser name match the config file name, just for clarity) and do the following:

We use Ruby’s YAML library to open our config file, then read the contents (scoped by the Rails environment; development, test or production), converting it into a Hash and then store it.

Where do we store it?

Every Rails application has an Application class (defined in config/application.rb) – when you name your application, this Application is scoped by the name of your app – so if you typed rails new whatever then config/application.rb will contain Whatever::Application.

And then within Whatever::Application there is an attribute called “config” that you can attach bits of data to. So we attach our hash to config.paperclip_file_options.

Then in my models I can do the following:

Of course, the same principle applies to any other configuration files – use an initializer to load the configuration as a Hash into your application configuration, and then that config can be referenced elsewhere in your application.

And there you have it – secret data is referenced from within your Rails application but never stored with your source code. This won’t work with Heroku (which uses environment variables to pass credentials around) but if you use Capistrano, this will keep your credentials away from prying eyes.

Do you know what to do but not how it works?

Ever wanted to understand why Rails views work the way that they do? Why variables from your controllers are visible inside your views?

Sign up below to get a free 5 part email course on how Ruby on Rails view rendering works and gain a deep understanding of the Rails magic.

We will send you the course, plus the occasional update from this web-site. But no spam, we promise, and it's easy to unsubscribe