support specifying path to `.env.keys` file
this would unlock the ability to store the .env.keys file as a secret file - similar to what Render and others support:
I'm going to +1 this, with some context.
I have made the mistake of adding, .env* to .gitignore, but forgetting to add .env* to .dockerignore, resulting in plaintext .env in a docker build artifact.
As long as .env.keys is present in my git repo, I think it's vulnerable to being leaked this way, or another way I haven't thought of yet. I would prefer it be out-of-band, safe in a place like ~/.config/dotenvx/
use dotenvx ext prebuild to make sure that never happens again in Docker.
RUN curl -fsS https://dotenvx.sh | sh
...
RUN dotenvx ext prebuild
CMD ["dotenvx", "run", "--", "node", "index.js"]
use dotenvx ext precommit --install to make sure it never happens in git.
$ dotenvx ext precommit --install
[dotenvx][precommit] dotenvx precommit installed [.git/hooks/pre-commit]
I would prefer it be out-of-band, safe in a place like ~/.config/dotenvx/
this is a good idea and something we'll consider.
ease of use and per project is still very important so I don't think it will be the default, but it will be an option that it will be easy to switch to as your default.
Another use case I would prefer is for monorepos to be able to have global .env.keys at the root of the repository. Having to copy-paste keys to multiple apps on onboarding is annoying.
So going up, up, up, up like, let's say, prettier and Node does when resolving modules to the root, is another good option. As doing --keys ../../.env.keys while OK and better than the workaround (like script that copies root one to apps below), is a tiny bit annoying/verbose :)
I believe this feature would be highly beneficial, allowing users to decide how to manage .env.keys files within a monorepo or any type of project. In my use case, I prefer a project structure like this:
.
├── .env.keys
└── apps
├── app1
│ └── .env.encrypted
└── app2
└── .env.encrypted
With this setup, I can define scripts in my package.json while specifying the key file (maybe using a -k option), for example:
...
"scripts": {
"app1:encrypt": "dotenvx encrypt -f ./apps/app1/.env.encrypted -k ./env.keys",
"app1:serve": "dotenvx run -f ./apps/app1/.env.encrypted -k ./env.keys -- serve-app1",
"app2:encrypt": "dotenvx encrypt -f ./apps/app1/.env.encrypted -k ./env.keys",
"app2:serve": "dotenvx run -f ./apps/app2/.env.encrypted -k ./env.keys -- serve-app2",
},
...
This approach avoids dealing with key concatenation for identical .env.xxx filenames (as discussed in #242). Additionally, if someone prefers to have separate .env.keys files for each app, they can do so by specifying the corresponding .env and .env.keys files easily. With such flexibility, we don't need to come up with new mechanism for different monorepo design. I hope this feedback helps improve the tool, and thank you for your hard work.
chatgpt keeps suggesting -k option to consume .env.keys but it's not really an option, yet?
no it's not. thanks a lot chatgpt, lol.
+1 to get keys like dotenvx -k ../../env.keys -f ./.env.development.
I'm building an app through a monorepo, and it would make things easier.
@motdotla do you have a roadmap for this feature?
keep all the thoughts coming here everyone. i haven't settled on a solution yet and am letting this one simmer for more comments and context. i'm also busy building dotenvx pro which will additionally explore some of this - but in a very holistic and team focused way.
effort started here: https://github.com/dotenvx/dotenvx/pull/486
released in 1.30.0. thank you everyone for your patience. let me know if you run into any edge cases but so far it feels pretty solid.
Hi @motdotla
Thank you so much, works perfectly for our use cases.
What do you think about changing the default for -fk to the cwd?
- -fk, --env-keys-file <path> path to your .env.keys file (default: same path as your env file)
+ -fk, --env-keys-file <path> path to your .env.keys file (default: current working directory)
Would you agree that most users would want a single .env.keys at the project root?
.
├── .env
├── .env.keys
├── .env.staging
├── backend
│ ├── .env
│ ├── .env.staging
│ └── …
└── frontend
├── .env
├── .env.staging
└── …
With this setup and the proposed change, the following command:
dotenvx encrypt -f frontend/.env
would suffice instead of requiring:
dotenvx encrypt -fk .env.keys -f frontend/.env
Looking forward to hearing your thoughts! 😊
i considered that, but decided against it for two reasons:
- symmetry: using
require.config(envKeysFile:)doesn't fit thecwdapproach well - since that file is nested in a monorepo and the .env.keys is../..back. - mixed behavior: by default
dotenvx encryptplaces the.env.keysfile next to the.envfile - wherever you encrypt it from. changing that tocwdbut ONLY when using-fkrequires the user to make a cognitive context switch. i decided to avoid that.
All that said, I agree this is a wart. It's not immediately intuitive. I considered that as well, but because this is for advanced users and won't be used all that often (except for monorepo users who tend to be advanced users already) we are going to just live with this wart in the tool.
Thank you for the detailed explanation! 🙌 makes sense.
I wrote a ZSH wrapper to set a default for -fk to simplify my workflow.
It might help others who use .env.keys often (especially in monorepos):
dotenvx() {
# Default value for -fk
local default_fk=".env.keys"
# Array to store new arguments
local new_args=()
local add_fk=true
# Check if command supports -fk
local allowed_commands=("run" "get" "set" "keypair" "decrypt" "encrypt")
if [[ ! " ${allowed_commands[@]} " =~ " $1 " ]]; then
# If command not in allowed_commands, execute as is
command dotenvx "$@"
return
fi
# Iterate through all passed arguments
for arg in "$@"; do
if [[ "$arg" == "-fk" || "$arg" == "--env-keys-file" ]]; then
# If -fk or --env-keys-file is found, do not add the default value
add_fk=false
fi
if [[ "$1" == "run" && "$arg" == "--" ]]; then
# Add -fk with the default value before the separating --
if $add_fk; then
new_args+=("-fk" "$default_fk")
add_fk=false
fi
fi
# Add arguments to the array
new_args+=("$arg")
done
# Add -fk with the default value if necessary
if $add_fk; then
new_args+=("-fk" "$default_fk")
fi
# Execute the original dotenvx command with the new arguments
command dotenvx "${new_args[@]}"
}
This way, I can work with a default .env.keys in the project root, where I usually will execute the dotenvx command.
Thanks again for this great tool and for taking the time to explain your design choices! 😊