I think probably the main thing is that environment variables are a distinct and well-defined; they don't have to interact with anything else syntactically. This makes them nice to use, say, to pass secret API keys to your program in a way which is less likely to leak (apart from the "log all env variables" problem discussed in the post).
Consider say, aws-cli. If I have to pass the API key as an argument, I have to C&P it into every command I write, or write a shell wrapper, thus storing the key on a file, which could accidentally get checked in or leak in some other way. Same with a configuration file. But if I just once per shell session put the API key into an environment variable, then it's only stored in memory; virtually zero chance it will make it into a git tree, and not terribly inconvenient.
Similar if you need to pass an API key to the app running in a docker container. You don't want to rely on your docker container image itself being secret; and it's often very convenient to keep your Dockerfile in a git tree, so you don't want to explicitly set the command in the dockerfile to include your key. And do you really want to keep your config file on the data volume? Or create a special separate volume just for the configuration file (when in fact, you want the vast majority of configuration to be stored in your docker image)?
Much easier to just tell the system running your container, "When you start this container, set this environment variable to this secret value." Then the system knows to treat that environment variable with discretion.
The alternate would be to tell the system running your container, "Add this secret rune to the command line before running", or "Add this secret config file". Environment variables are much easier to reason about.
My question was about the blog posts assertion that something using environment variables to pass information was using a "ghost", but something like a command line option isn't.
I guess, maybe the difference is in when and where the env var is specified. If you do something like
```
FOO=bar
<hundreds of lines of bash>
myapp # uses FOO
``
Then I think the blog post author has a point - there's "hidden" information in the environment/context that the callee expects and will use. If you copied just the `myapp` line and stuck it somewhere else, it would lose the implicit `FOO` it expects to have.
Vs something like
```
FOO=bar
<hundreds of lines of bash>
myapp --foo="${FOO}"
```
or
```
FOO=bar
<hundreds of lines of bash>
FOO="${FOO}" myapp # at least this way it's explicit!
Consider say, aws-cli. If I have to pass the API key as an argument, I have to C&P it into every command I write, or write a shell wrapper, thus storing the key on a file, which could accidentally get checked in or leak in some other way. Same with a configuration file. But if I just once per shell session put the API key into an environment variable, then it's only stored in memory; virtually zero chance it will make it into a git tree, and not terribly inconvenient.
Similar if you need to pass an API key to the app running in a docker container. You don't want to rely on your docker container image itself being secret; and it's often very convenient to keep your Dockerfile in a git tree, so you don't want to explicitly set the command in the dockerfile to include your key. And do you really want to keep your config file on the data volume? Or create a special separate volume just for the configuration file (when in fact, you want the vast majority of configuration to be stored in your docker image)?
Much easier to just tell the system running your container, "When you start this container, set this environment variable to this secret value." Then the system knows to treat that environment variable with discretion.
The alternate would be to tell the system running your container, "Add this secret rune to the command line before running", or "Add this secret config file". Environment variables are much easier to reason about.