Skip to content

Instantly share code, notes, and snippets.

@jnicklas
Last active October 14, 2015 20:30
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jnicklas/b38dd245b0393d796523 to your computer and use it in GitHub Desktop.
Save jnicklas/b38dd245b0393d796523 to your computer and use it in GitHub Desktop.
Why do .env files exist?

Why do .env files exist?

Lately I've seen a lot of projects use .env files to store application configuration, files which look something like this:

FOO=bar
Bar=baz

There are a lot of tools which consume these files, like foreman and dotenv, so all seems good, the file contents are straight-forward, and everyone is happy, right?

I think these files are a bad idea.

First of all, what are these files, really? Are they shell scripts? Am I allowed to do this:

FOO=bar
BAR=$FOO

I guess probably not. In fact they don't really make sense as shell script, since there's no real way to execute these files and load the results into a shell. It's possible to source them into a shell, but since they're not exported they won't affect any programs started from this shell, so this is essentially useless.

In fact most programs which consume these files implement a parser which parses them into a data structure. See for example foreman's implementation here.

So if they're not shell scripts, and everyone parses them into data structures, .env files are in fact a serialization format. And if they are a serialization format, there are a couple of questions we should ask us:

  • Is it legal to quote values?
  • What characters can I use for quoting?
  • Are comments allowed in these files?
  • What encoding are they in?
  • What happens if I insert a null byte?
  • Is there any way to escape a newline?
  • Are windows-style line-breaks allowed?
  • Can lines be separated by semi-colons as in bash?
  • Can I put binary data in there?

And so on and so forth.

The problem is that .env files don't have a specification. Everyone who writes a parser for them essentially invents their own, probably slightly incompatible format.

We are left with two possible solutions:

  1. Use an actual shell script
  2. Use an actual serialization format

If you use the first option, be aware that you cannot use any of the tools which consume .env files. foreman for example silently ignores all lines which are prefixed with export. dotenv actually does the right thing and allows a leading export, but again, the behaviour differs between implementations. There's no common spec.

I think the second option is far better. There are a bunch of existing serialization formats which work just fine. You can use TOML, YAML, XML, JSON or whatever else you like.

Or someone could sit down and write a proper spec for the .env file format with a reference implementation. But really, why bother?

@dasch
Copy link

dasch commented Oct 14, 2015

The reason .env files are nice is because there's a direct mapping from the format to environment variables, so the cognitive overhead is minimal. There are definitely problems with the format, but the simplicity is undeniable.

@jnicklas
Copy link
Author

@dasch my concern is that there is a lot of hidden complexity in something seemingly simple. CSV files are simple, but implementing a correct CSV parser is actually not that easy. So if everyone goes and reimplements a parser for something, even though it seems simple, that doesn't even have a spec, we end up with subtle bugs and incompatibilities.

You could so something like this in TOML:

FOO = "bar"
BAR = "baz"

The only difference is that you have to surround the = with spaces. IMO there isn't much difference in cognitive overhead and you get a properly specified format in exchange.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment