vlucas / phpdotenv

Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.
BSD 3-Clause "New" or "Revised" License
13.17k stars 629 forks source link

One .env to rule them all #455

Closed antonioribeiro closed 2 years ago

antonioribeiro commented 4 years ago

Managing several '.env' files plus a '.env.example' is sometimes complicated, and frequently we get some of those files out of sync.

So, it could be a nice feature to be able to use a single .env file for all environments, by just hinting environments like:

DB_CONNECTION=pgsql // default, not found, or simply the same on all environments

DB_HOST.local=127.0.0.1
DB_HOST.testing=postgres
DB_HOST.staging=10.0.0.2
DB_HOST.production=172.17.0.101

And, of course, way of loading for loading the current environment:

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load('production');
GrahamCampbell commented 4 years ago

Thanks for getting in touch. I don't see the use case here, since your production secrets should never be committed to the repo? Why would you need to have production and local side by side?

antonioribeiro commented 4 years ago

Hello @GrahamCampbell !

Think about having 4 sites on Forge, plus one local .env file, and, yes, we are safe, so they are not commited to the repository.

Every time I make a change to my local .env file, I have to make the same change to the .env.example (not in question here!) and then go to 4 Forge sites and edit one by one, making the same changes, just changing those 5 new keys I just added, sometimes having to find the right place on each file where to put those keys. Some data will be the same, some will be different because they are private keys, but I still have to do all the work 4 times, and as a human repeating the same job, I will miss something, or forget one, or just be lazy and let the thing to be done later, and it will be missed.

Having a single .env file would allow me to

It's much simpler, faster, easier, less prone to (repetition) errors, and it also gives me visibility on all environments at the same time so it's also informative.

hakuno commented 4 years ago

It seems a limitation.

The basic parser for INI can read this

[FAILOVER]
NODE[]=8.8.8.8:80,443
NODE[]=1.1.1.1:80,443

[HEALTHCHECK]
INTERVAL=15000
TIMEOUT=3
RETRY=3

with parse_ini_file(".env", true, INI_SCANNER_TYPED);

So I can have grouping & arrays with complete happiness.

But we can't do the same with dot-env. Does it?

It's interesting to develop a dot notation feature.

So we can retrieve with staging.db_host (or db_host.staging as said).

+1 for dot notation 👍

ps. It sounds like the config helper of Laravel as such.

GrahamCampbell commented 4 years ago

I am going to defer the decision of whether this is wanted to @taylorotwell and @jbrooksuk, if your use case is purely Forge.

selcukcukur commented 4 years ago

This seems unlikely to be a correct use. @antonioribeiro

antonioribeiro commented 4 years ago

@GrahamCampbell , I keep hearing this, but the "use case" argument for denying something is not the best for a community as big as PHP or Laravel, because, the bigger the community the nearest from infinity "use cases" can get.

My use case is not your use case and will probably not be from thousands of other developers. My use case can also change according to the client I'm working for or the infrastructure I'm deploying. Have you tried to update a bunch of .env keys on an Azure App Service? It's a nightmare! Our last app is being deployed to it, we have dozens of keys, and the only way to do it in bulk is to update a JSON file like this:

image

This one has 640 lines * 3 environments = 1920 lines, I broke this JSON several times, I also pasted the wrong keys to the wrong environment, because, yes, I'm not good doing boring repeating tasks.

So maybe the use case is reducing repetition and human errors?

Otherwise you have to click to edit one-by-one. But they are super secure, so it would not be a big security problem to have the keys for all 3 clusters in a single JSON file. The amount of errors I make would drop considerably, because, yes, I'm not good doing boring repeating tasks.

The real use case here is namespacing the .env file.

Forge was just an example, and Forge, as far as I can tell is just a server provisioning boxes supporting natively only a few services, but the use case is any server, any box, any service deploying Laravel apps, on AWS, Azure, Google Cloud, Docker, Kubernettes, Linode, Vultr, Scaleway, DigitalOcean, OVH, Alibaba... managed by Forge or anything else, and believe me, there are a lot of other dashboards doing the same out there, and many of those services have their own deployment and app management systems too.

hakuno commented 4 years ago

@antonioribeiro I guess you need to overcome this limitation and look for some DevOps approach. I'm unsure how much the staff want to increment one new feature like that. Unless you've a ready PR for review.

Ps. Actually, those settings are related to many environments (in your use case closely). If you set all environments rather than current one, so it becomes a configuration instead of set of environment variables.

GrahamCampbell commented 4 years ago

PHPDotenv already natively supports loading more than one file. Why can't you just load a base file and then a file specific to the environment you have?

XaeroDegreaz commented 4 years ago

@antonioribeiro - Could you possibly use something like array_merge to do what you want? Load your default file, then load another for a different environment, and merge the arrays while overwriting keys (where necessary)? It may be a stop-gap measure if there isn't going to be official support for it.

dobryak commented 3 years ago

@antonioribeiro - I think GNU Make can help you solve the problem.

Makefile:

.env: .env.example
    @./scripts/update_env

then just:

$ make

So, you can keep your .env file updated.

nahiyan commented 3 years ago

Can they consider using TOML for the .env files? The .env files, especially of Laravel, would be so much cleaner!

frob commented 2 years ago

Sounds more like you don't want to use .env files for things. Also, not really understanding how your wouldn't need to edit the values in all the places if a file was changed or a field added.

GrahamCampbell commented 2 years ago

I'm going to close this out for now as out of scope of what the package was intended to do.