Skip to content

Improve Craft CMS "settings management" (writing to project .env) #7233

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 task done
timkelty opened this issue Apr 25, 2025 · 13 comments
Closed
1 task done

Improve Craft CMS "settings management" (writing to project .env) #7233

timkelty opened this issue Apr 25, 2025 · 13 comments

Comments

@timkelty
Copy link
Contributor

timkelty commented Apr 25, 2025

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem?

The Craft CMS project type writes a number of CRAFT_* vars to the project's .env file, which is not ideal for a few reasons:

  • Craft itself doesn't natively enforce .env usage, so it relys on someone using vlucas/phpdotenv
  • We've found it not uncommon for people to upload their local .env file to a server and use as a base for editing. Usually they are aware enough to change the CRAFT_DB_ vars, but often times don't realize CRAFT_WEB_ROOT was added by DDEV, leave it in place, and break their remote app.

Describe your solution

The way things are implemented now seems to be somewhat by chance and a fundamental misunderstanding of how the "settings management" feature is intended to be used.

Ideally, DDEV wouldn't touch the project's .env file, and instead inject the environment variables directly into the containers.

Describe alternatives

It appears that writing .ddev/.env is one option for that, but writing to YAML may also be an option.

Additional context

@rfay
Copy link
Member

rfay commented Apr 25, 2025

I would really like to see us use .ddev/.env.

Note that environment variables defined in .ddev/.env are populated for all containers for the project.

It seems like just creating/managing .ddev/.env would solve the Craft problems ?

@timkelty
Copy link
Contributor Author

Yep, sounds like a plan @rfay

@rfay
Copy link
Member

rfay commented May 1, 2025

@timkelty we'll need at least your reaction and followup on

@timkelty
Copy link
Contributor Author

timkelty commented May 1, 2025

@rfay On my list today!

@stasadev
Copy link
Member

stasadev commented May 19, 2025

Craft itself doesn't natively enforce .env usage, so it relys on someone using vlucas/phpdotenv

While it's not required, it's used by the template https://github.com/craftcms/craft, and .env example files show CRAFT_DB_* variables.


We've found it not uncommon for people to upload their local .env file to a server and use as a base for editing. Usually they are aware enough to change the CRAFT_DB_ vars, but often times don't realize CRAFT_WEB_ROOT was added by DDEV, leave it in place, and break their remote app.

I opened:


From Discord https://discord.com/channels/664580571770388500/1372597483443589264:

Using .ddev/.env.web may not be an obvious change for existing apps (or new apps created from the template https://github.com/craftcms/craft):

I'm still getting the A new install message when I run ddev craft install, which Craft only shows when it doesn't see valid database credentials.
I thought this would be fixed by running ddev restart, but it is not. I found the problem, it's that we're also setting the CRAFT_DB_* variables in our own .env

@MattWilcox
Copy link

Just adding in here as general feedback so it's not lost in Discord.

This change is something I just don't want in our projects, and all it's done in introduce a new thing I've had to add into the project's root level .gitignore file, and a level of confusion about what's actually happening.

Context: I was working on our long-standing starter project, from which other web projects are built, and the new behaviour added the .ddev/.env.web file into that base project's Git repo - but that file has variable values specific to the instance (PRIMARY_SITE_URL).

I appreciate this may be a little niche, but as a general thought - I was under the impression that .env anything should not be in GIT, because the purpose is that these are environmental data that changes, and shouldn't be in Git because those values differ based on where you're actually running the project.

Frankly, for us, we don't want any of the stuff DDEV adds into .env as we just do not use those values in our projects. It's already set up and running. Likewise, we don't want or need the new .ddev/.env.web either - and now it's there, I don't actually understand which .env files' values will be being used! The one in .ddev, or our standard one at the standard location.

@stasadev
Copy link
Member

Thank you for the feedback @MattWilcox.

Frankly, for us, we don't want any of the stuff DDEV adds into .env as we just do not use those values in our projects. It's already set up and running. Likewise, we don't want or need the new .ddev/.env.web either

It can be disabled completely:

ddev config --disable-settings-management

@rfay
Copy link
Member

rfay commented May 20, 2025

As you see @MattWilcox this was requested by @timkelty of Pixel & Tonic. We generally only do explicit CMS integrations in collaboration with the communities involved, and this one was done over time with collaboration from the Craft CMS folks.

@brandonkelly
Copy link
Contributor

brandonkelly commented May 20, 2025

We just tagged new craftcms/craft releases for v4 and v5, which no longer include default CRAFT_DB_* env var values in .env.example.dev file (which the default .env file is copied from on composer install).

Tested installing Craft 4 and 5 on an older version of DDEV as well as v1.24.6, and all works as expected. Older versions will append the CRAFT_DB_* vars to .env, and v1.24.6 will add them to .ddev/.env.web. Either way, Craft is configured correctly and able to connect to the DB immediately after running ddev create-project.

Context: I was working on our long-standing starter project, from which other web projects are built, and the new behaviour added the .ddev/.env.web file into that base project's Git repo - but that file has variable values specific to the instance (PRIMARY_SITE_URL).

I appreciate this may be a little niche, but as a general thought - I was under the impression that .env anything should not be in GIT, because the purpose is that these are environmental data that changes, and shouldn't be in Git because those values differ based on where you're actually running the project.

@MattWilcox That’s true for the root .env file, but this is a special case. DDEV isn’t adding any sensitive info to .ddev/.env.web, or anything that would change from one dev environment to the next; it’s all just a replication of info that’s already being stored elsewhere in .ddev/.

@timkelty
Copy link
Contributor Author

timkelty commented May 20, 2025

It's also worth noting that .ddev/.env.web and .env are fundamentally different: Vars in .ddev/.env.web are actually injected into the DDEV containers by docker, where .env is loaded by the vlucas/phpdotenv and the project itself.

@MoritzLost
Copy link

@timkelty @brandonkelly I'm figuring out how to address those changes in our existing projects and our Craft boilerplate. Removing the CRAFT_DB_* variables from the .env doesn't work for me because we only have a single .env.example, not three different examples files for dev/staging/production. So we're always copying .env.example to .env during composer install. That means we would have to manually add those variables to the .env in any staging or production system, which is awkward.

I found a much better solution, in my opinion, is to switch from Dotenv\Dotenv::createUnsafeMutable to Dotenv\Dotenv::createUnsafeImmutable in our bootstrap.php. This means that existing environment variables can never be overridden. This is a saner default anyway. And it means I can still have the CRAFT_DB_* variables in my env, but they won't take effect if ddev has already set those variables, so the ddev-injected variables always have precedence and will always work, even if another colleague hasn't updated their .env yet.

This might be a good default for craftcms/craft as well?

Correct me if I'm missing something …


@MattWilcox I agree with you that even the env files in .ddev shouldn't be tracked in git, I've added this in my top-level .gitignore when we started using ddev:

/.ddev/.env
/.ddev/.env.*

@brandonkelly
Copy link
Contributor

@MoritzLost We used to use createUnsafeImmutable(), but changed it in response to craftcms/craft#82.

We just discussed whether it would make sense to switch back in light of this DDEV change, but decided to keep it as-is, as the (now) current behavior is more in line with expected behavior at first glance. (We expect it would confuse people to have environment variables defined in .env which aren’t getting picked up.)

That said, if you’d prefer to stick with a single .env.example and understand the effects of going with createUnsafeImmutable(), you are definitely free to go with that in your own projects!

@MoritzLost
Copy link

@brandonkelly Good to know the history, thanks! Yeah, it might be confusing for new devs if their .env doesn't take effect.

We'll stick with using createUnsafeImmutable() for now. ddev only sets the variables that are absolutely required for the web container to work correctly, so having those take precedence makes sense for us. But I can see that using the mutable approach is a more reasonable default for the starter project.

I've added a note at the top of our .env.example to avoid future confusion:

# Environment variables are loaded in `bootstrap.php` by vlucas/phpdotenv
# Existing environment variables (e.g. provided by DDEV) always take precedence
# and are not overridden by .env values. If a variable is already set in the
# environment, the .env value is ignored.

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

No branches or pull requests

6 participants