Developers who are familiar with the “twelve-factor” app know that configuration should be stored in the environment (loaded via env vars), not in the code. If you’re writing a Rails application you may want to use the
dotenv gem, which allows you to store env variable in a handy series of files such as
.env, .env.development, .env.test and so on. You can read the gem readme for all the details.
Since configuration varies with time and you may be working with many other developers, it is quite handy to store these env files in your git repository, but there’s a big caveat: you should not store passwords, secrets and tokens inside a git repo for security reasons, unless they’re encrypted.
Dotenv has no builtin encryption facility, so here at Mikamai we followed this rule for a while, avoiding to commit any sensible config data inside the project repository.
Unfortunately this solution didn’t work perfectly: we had strong security, but we faced some practical problems.
Every time a new developer joined a project they had to ask for the configuration file to another dev, who in turn could have a file which was not updated anymore with old keys/values or missing data. Then developers were asked to document the keys they added, but sometimes they forgot. No need to blame them, after all we’re just humans.
The gem is quite simple, it just patches some dotenv classes in order to allow the loading of the encrypted versions of dotenv files, such as
.env.enc, .env.development.enc and so on. The encrypted files have lower priority, so you can always override them locally with the corresponding clear dotenv file (ie. for
.env.development.enc you can use
So, how does it work? It’s quite simple: once you’re in your rails repo and you added the
dotenv_secrets gem to your Gemfile, you can do in the shell:
# create the sekrets key file: touch .sekrets.key echo "42" > .sekrets.key # and gitignore it: echo ".sekrets.key" >> .gitignore # create and edit the dotenv file: touch .env.enc bundle exec sekrets edit .env.enc # the file opens in your editor # verify that when you close the file it # gets automatically encrypted: cat .env.enc # add the config file to the repo and commit: git add .env.enc git add .gitignore git commit -m 'Add encrypted env configuration'
And that's it! Now, you need to distribute securely only the key, not the whole configuration file, which remains always available and up to date inside the repository.
I hope this gem can be useful to other teams, and of course if you have comments/issues you can reach me on the gem page on github.