32 ms·
Show HN: From dotenv to dotenvx – better config management
- bdcravens 2y agoSeems odd to announce new features without calling out to the fact that libraries with the same name in other languages have had those same features for years. (for example, the dotenv gem in Ruby)
- smartplaya2001 2y agoNode.js already has built in support for .env https://nodejs.org/en/blog/release/v20.6.0#built-in-env-file-support https://nodejs.org/en/blog/release/v20.6.0#built-in-env-file...
- bdcravens 2y agoTrue, but the dotenv npm package has been around much longer than that support (11 years vs 9 months), and the .env support in Node doesn't yet support features like auto-inclusion of environment-specific files.
- languagehacker 2y ago[flagged]
- deleted 2y ago[deleted]
- boxed 2y agoI don't get it. Dotenv is only good for local dev. Otherwise you should put your secrets in environment variables (the "env" in ".env"). That people put .env files in prod is a mistake itself, and the proposed fixes here seem to not really do much about that.
- isoprophlex 2y agoJust set those env vars in your IDE. Let your IDE or docker-compose or whatever read an .env file if you must. But don't do it directly from your application code, indeed you're one lazy dev away from putting an .env file on prod servers. Using dotenv-like constructions is, in my eyes, an antipattern.
- aendruk 2y agoAnd it need not even be an IDE. Whatever environment you use for development, set environment variables in that.
- Tainnor 2y agoPlease don't configure important things in the IDE. IDE configs are notoriously fickle and checking them into the repo usually just leads to a lot of problems in my experience, plus it will mean duplicated effort every time you need to do something from the CLI.
- adolph 2y ago> Just set those env vars in your IDE. How is that different from a dotenv, other than location of where the k/v persists?
- hu3 2y agoI've seen so many .env files in production that I don't even wince anymore. I just formalize the finding by email and carry on.
- daralthus 2y agoYou can commit your secrets as an encrypted vault with this. Then decrypt it with a key where needed: locally, on CI, on prod, etc. This is basically a simplified version of Hashicorp's Vault, GCP key vault etc. with some less granularity on user authentication. It solves the issues around .env.example and is perfect for gitops. You have all your secrets for all your envs ready, while you only need to set a single env var (the private encrpytion key) on your specific hosting environment. You could even use separate keys per env, eg.: to give access to a developer to staging only. Mozilla's https://github.com/getsops/sops https://github.com/getsops/sops is another contender but with a more complicated (and perhaps more flexible) key management.
- daralthus 2y agoWould be nice to be able to configure which .env file to read as an environment variable. Why? Imagine a package.json with this line: `start: dotenvx run -f .env.local -f .env -- node index.js` Instead of the -f flag, which now cannot be overriden, one could invoke it with `DOTENV=.env.staging npm run start`
- fiddlerwoaroof 2y agoOr just have the environment variable used after the flags are processed
- vinnymac 2y agoYou can, you just need to define the private key. For example DOTENV_PRIVATE_KEY_PRODUCTION Would provide it with the information it needs to read .env.production
- atulvi 2y ago[flagged]
- throwaway240403 2y ago"Config Management" means something else to systems folks. Suggest adding "for node projects" or something akin to the title to clarify.
- dymk 2y agoIt's not node specific like dotenv, it's a generic tool for launching processes with (optionally encrypted) environment variables.
- deleted 2y ago[deleted]
- jitl 2y agoSecrets in env vars in production is not too secure either, ideally you’ll move to your app pulling secrets in-process from your infrastructure at boot-up or upon use. This also gives a nice advantage of not needing to rebuild the app or container or whatever to rotate a secret.
- Etheryte 2y agoThis just moves the problem to a different step. How are you going to manage access to said secrets, especially when your application lives off premises?
- nevir 2y agoMany hosting environments give you this. For example AWS gives you multiple ways of injecting secrets as env vars into your containers when they boot up (ECS + secrets manager, EKS, etc)
- jitl 2y agoThis is still “env vars”, easy to read from /proc/*/env too see the decrypted secrets from a different process. Versus in-process only secret fetch where you’d need to scan the memory pages of the app, which is a bit harder - especially if you keep the credentials in memory in a scrambled format so a simple scan on process memory for “secret_prefix_” doesn’t find them.
- Spivak 2y agoIf an attacker can read other processes' envs you've pretty much lost as they're 1. Inside your process which means they can see the decrypted values. 2. Root which means they can get into your process to see the decrypted values. I'm not sure if your average dev has a threat model that assumes in memory scrambling let alone leaked env vars. After all we're talking about the standard way to do it being populating a file with the decrypted secrets and just leaving it there. All the security is already kernel security. I'm honestly not sure who dotenvx is aimed at. - No one security conscious is going to be cool just making the cyphertext available publicly or even internally. - Someone scrambling in-memory secrets isn't using dotenv to begin with, is using SecretsManager and the like, and probably doesn't want to change those to now go through the filesystem. You now get less auditing because all those secrets are bundled and you now only know "they accessed the decryption key." - And someone using dotenv for secrets doesn't have a threat-model where this meaningfully improves security.
- ashenke 2y agoThere's a typo in the article, if the author reads this : > But I think we have a solution to all three today - with dotenvx. In reverse problem order The URL in `dotenvx` points to https://gitub.com/dotenvx/dotenvx https://gitub.com/dotenvx/dotenvx (gitub without the h)
- ssahoo 2y agoHey this link is malicious. It redirects to location: http://ww99.gitub.com/dotenvx/dotenvx http://ww99.gitub.com/dotenvx/dotenvx and then some site blocked by ublock
- bluelightning2k 2y agoI don't really understand why this is a new project. Seems it would have been pretty simple to add these in a backwards compatible way. It would only break in cases where people's values specifically started with "encrypted:"
- daralthus 2y agoIt was added in a backwards compatible way, but the author decided to make a breaking change with this release. The previous (IMHO superior) version was generating a .env.vault and a .env.keys from a .env file. Leaving the .env plain text and .env.vault encrypted.
- bluelightning2k 2y agoMaybe the simple idea is to start a company. Nothing wrong with that. It's definitely what I would do. First envx then "envx vault"
- OJFord 2y agoEven without backwards compatibility, why not just a breaking change in the same project? Don't get it either. I've never used it (knowingly) but if I did and wanted to use this new version/project even the CLI name change to append 'x' would be annoying (I'd probably alias /symlink it).
- triyambakam 2y agoWhether good or bad, it's marketing
- VWWHFSfQ 2y agoI always used foreman [0] which I found to be superior to dotenv in every way. Even superior to this new dotenvx [0] https://github.com/ddollar/foreman https://github.com/ddollar/foreman
- edward28 2y agoNot to be confused with the larger foreman[0] also written in ruby. [0] https://theforeman.org https://theforeman.org
- itslennysfault 2y agoYeah, this is a really weird post for me. Before dotenv existed I used Foreman. It worked basically exactly how "dotenvx cross-platform" works (as a global command line). I switched to node-foreman because I largely switched to working on node projects and didn't want devs to need to have ruby installed. Then, at some point I switched to dotenv, and I don't even remember why.
- pictur 2y agoI think for some reason people don't like such simple tools. I think it seems more reasonable to deploy a vault service running on kubernetes with jenkins. In some comments, they didn't even understand what the tool was for. Dear dude, you can travel between dimensions with this tool.
- brigadier132 2y agoEncrypting secrets and committing them seems very convenient but I'm paranoid about these sorts of things. Can anyone tell me why this would be a bad idea? One reason I can think of is that normally with secrets I actually don't keep any copies of them. I just set them in whatever secret manager my cloud environment uses and never touch them again unless I need to rotate them. Meaning there is no way to accidentally expose them other than by the secret vault being hacked or my environment being hacked. With this approach if someone gets access to the encryption key all secrets are exposed.
- Atotalnoob 2y agoUsing encrypted secrets provides a way better developer experience than using a vault. Typically, developers can’t change production secrets in vaults and need to follow some other protocols. Encrypted secrets mean you deploy everything along side the secrets. The developer experience is great, but the biggest issues I have faced while using Kubeseal were 1. Developers HAVE the secret in order to encrypt it. This can be not ideal as then they can use these secrets in production or leak them 2. The secret encryption key change causes the need to re encrypt everything. 3. People don’t understand the concept.
- prepend 2y agoI disagree. Using vaults isn’t that bad. And I’d also like developers to never actually know the secrets. It’s a learning curve, but I think it’s best to just bite the bullet and use a vault rather than trusting developers to know and manage secrets properly.
- nahtnam 2y agoAnother benefit is that debugging secret changes is a lot easier. We've had a couple of cases where someone changes the secret in a vault and that causes problems and no one can tell what changed between two deploys
- solatic 2y agoThe biggest issue with storing secrets in version control with the code is that past secrets are never relevant after they have been rotated. This makes rollbacks risky. Consider: 1. Create secret v1 2. Code v1 3. Deploy 4. Secret v2 (rotation) 5. Code v2 6. Deploy 7. Oops, need to roll back to v1 (from step 2) 8. Outage, because the secrets in step 2 are not the secrets from step 4
- hermanradtke 2y agoI’ve been using dotenv-cli for a long time now. I appreciate the encryption, but I will keep loading secrets from a vault instead.
- golergka 2y agoI don't think encryption is a good idea, and the reason is forming bad habits. Now developers have a very strong and non-ambiguous habit: never put .env files in version control (except may be for .example.env). However, with this, you'll get accustomed to commit .env in _some_ projects, so you'll easily slip and commit it in another project where the vars are not encrypted.
- jppope 2y ago[flagged]
- deleted 2y ago[deleted]
- mplanchard 2y agoSeems pretty similar to sops[0], but without the encrypted-by-default feature that makes sops feel significantly safer for secret management. Sops also integrates easily with AWS and other existing key management solutions, so that you can use your existing IAM controls on keys. I mentioned in another comment, but I've been using it over five years at two jobs and have found it to be great. [0]: https://github.com/getsops/sops https://github.com/getsops/sops
- pmccarren 2y agoI too have been using sops for years, and agree -- dotenvx encryption seems very similar to sops. I'd prefer an integration between dotevnx and sops where dotevnx handles the UX of public env and injection, while leveraging sops for secret management and retrieval. Additionally, being able to have multiple keys for different actors is important. Having a single `.env.keys` file feels risky and error prone. dotenvx encourages adding your various env files, such as `.env.production`, to vcs, and you're one simple mistake away from committing your keyfile and having a bad day. If sops is not to be integrated, dotenvx could take some inspiration where the main key is encrypted in the secrets file itself, and you can define multiple age key recipients, each of which can then decrypt the main key.
- hadlock 2y agoI've been using sops in production since at least 2017, plus it has excellent compatibility with containerized infra tools like helm and other infra tools like terraform (both technically using plugins, but helm secrets and the carlpetts terraform plugin have been around for ages and are widely used.
- rrgok 2y agoCan a kind soul point me some documentation on how to put .env in a vault correctly? Possibly open-source solutions? If the vault is password protected, aren't you just adding one more indirection and nothing more? How is that helpful, since now I have to write the vault password in clear-text somewhere such that my application can read the env file from the vault?
- c0brac0bra 2y agoA lot of modern cloud deployments read from a secret management system or vault at deployment time, and the secrets are made accessible to the application through various indirect methods so they cannot be accessed later on (i.e. if someone were to gain access to a running Kubernetes container). At no point does the application have access to the vault itself, and access to read the vault is guarded by IAM role permissions.
- rrgok 2y agoOh well, I really appreciate you taking the time to explain it. But honestly, I didn't understand a word. I recognize it is my lack of knowledge. I hope someone can do me a ELI5.
- freeone3000 2y agoSomething else pulls from the vault and exposes it as a regular env var to your process. The .env file is a workaround to get this running locally! For open source, the simplest to explain is using a k8s secret mounted to a pod — pod identity allows access to the secret via rbac, which cannot be faked. Only that pod has access to that secret. But your process, running on the pod, sees it as an env var.
- boarnoah 2y agoThat doesn't cover what the GP was talking about with > (i.e. if someone were to gain access to a running Kubernetes container) right? Since those would still be secrets available in the env. I get that if someone has access to read your envvars, its a foregone conclusion already (about how compromised you are). However IIUC, the part of the point of doing things in memory with reading secrets (like with a Secrets Manager, is to eliminate having to keep secrets around as envvars/secret files in the runtime?
- ComputerGuru 2y agoWe’ve been pushing for committing encrypted secrets for many years now, and have written an open source spec and implementation in multiple languages: https://github.com/neosmart/securestore-rs https://github.com/neosmart/securestore-rs
- curiousdeadcat 2y agoI got so excited, but it doesn't seem to support multiple keys and seems overly eager to encourage people to leave a valuable key lying around on disk. So if a single dev machine is compromised, all of your prod secrets are exposed? I wish this were closer to sops with support for gpg and or ssh keys. Because sops is a great idea locked in a questionable codebase.
- ComputerGuru 2y agoHappy to discuss a proposal to add asymmetric key support to the project in the GitHub issue tracker. Although I'm not sure how the security changes with an asymmetric key, as either way the worst case scenario is the same? Note that you don't have to leave the key "lying around" as you can secure it the same way you would an asymmetric key. And it certainly beats leaving the plaintext secrets themselves lying around in a .env file or similar. EDIT: I see you were saying "dev machine" exposes "prod secrets" but that's not the case. The protocol is designed so you would have secrets.json and secrets.prod.json, encrypted with different keys and (necessarily) managed separately but with the same tools and api. Dev machines being compromised compromises dev keys, not prod keys. Read the last section in the README on GitHub for more on the dev/prod split.
- curiousdeadcat 2y agoAsymmetric keys mean you can you can have per-dev or per-team keys and allow one team to rotate them and resign them for all other consumers. I don't know how you'd do that with symmetric keys. This is an important feature of sops, imo. It also means I can do things like seal them to a key that is stored in KeyVault and then allow the transparent retrieval of that key at runtime on Instances that have been given an identity with access. This means that production secrets are sealed in place and only openable by effectively authenticated workloads. And if you use sops-nix, this becomes a "setup once and never think about it ever again, ever" kind of operation.
- ptdorf 2y agoSo.. it just swapped ignoring `.env` for `.env.keys`?
- wodenokoto 2y agoOn my phone so can’t double test, but can’t you get this by adding “export” in front of every line in your env file and then source before running command? I suppose if you don’t want it to stay after execution i believe you can: > $(source .env; my command) I’m sure there is a fairly straightforward way to encrypt and decrypt a local file
- bogdan 2y agohttps://github.com/getsops/sops https://github.com/getsops/sops
- newzisforsukas 2y agoBeing able to source the file is the main benefit of using a .env file, IMO. Otherwise, you can just use any format for config management.
- ruined 2y agodotenv has features that include conditional selection and ordered merging of env files, which are configurable by dotenv's runtime and buildtime APIs.
- wodenokoto 2y agoAt least merging can happen by sourcing .env files in order (last to be sourced has priority) But I do agree that at some point you want a tool to orchestrate these things and guide your usage so you don’t have to reinvent the same lines of code all the item
- eternauta3k 2y agoNow take that a step further with Environment Modules and you can source them from any shell or scripting language: https://modules.readthedocs.io/ https://modules.readthedocs.io/ (without creating a subinterpreter)
- gkfasdfasdf 2y agoIf in bash, you can use the 'allexport' option and source the .env without having to add 'export' in front of every line: #!/bin/bash set -o allexport . .env set +o allexport cmd
- bradgessler 2y agoI really wish 1Password would ship an environment manager for their op CLI.
- michaelmior 2y agoWith leaking secrets being such a big concern, it seems wise to require that secrets be encrypted to use dotenvx. That is, it will only work with encrypted secrets. As others have commented, this doesn't eliminate the risk entirely, but I think having a tool that doesn't support unencrypted secrets at all, although a bit less convenient, is a win.
- akvadrako 2y agoEncrypted with what key? Do you just mean obscured?
- projektfu 2y agoThe utility has a means of encrypting them with public key cryptography so that the plaintext is never in your development directory. GP thinks this should be made mandatory.
- airtonix 2y agopoint is: where and how you do get this key when in prod?
- progx 2y agoThe "securest" way is, you start your app and the app awaits the input of the key, it is only in the RAM. But in reality, nobody will do that.
- michaelmior 2y agoPart of my point is that if you care about security, you need to be thinking about these things. Forcing encryption then also forces you to think about how to provide the key. Of course, it's possible to do this in a very insecure way that defeats the purpose of encryption in the first place, but I think it moves things in the right direction.
- cced 2y agoThere are a lot of ways of doing this, sealed secrets is one, mozilla sops is another.
- 0xbadcafebee 2y agoThe whole idea of using environment variables for configuration information is good, but ultimately flawed, and we are way past the point where this should continue to be the status quo. Environment variables are great for configuration because: - you can inherit them from a previous application or application(s) - you can override them in each environment you run your app in - you can pass them on to other applications - they are globals that can be loaded by libraries - they're not hardcoded in the code, so easier to change things without rebuilding, easier to reuse in different ways/environments/configurations - the OS has primitives for them - they're simple Environment variables are bad for configuration: - because (by default) when set in application, they are passed on to all future applications/forks/execs - they are often dumped as part of troubleshooting and aren't considered confidential - they can often be viewed by external processes/users - there are restrictions on key names and values and size depending on the platform - typical "dotenv" solution doesn't necessarily handle things like multi-line strings, has no formal specification - no types, schemas What we actually need that environment variables are being used for: - configuration information passed at execution time that can change per environment - loading or passing secret values - development environments - production environments So what would be a good alternative? - an application library ("libconfig") that can load configuration of various types from various sources in various ways - support for configuration types: key-value, file/blob, integer/float - support for confidentiality (require specific function to unseal secret values; in programming languages the intent would be you can't just print a stringified version of the variable without an unseal function) - support for schema (application defines schema, throws exception if value does not match) - support allowing a configuration to be overloaded by different sources/hierarchies - support passing a configuration on to other applications - support tracing, verbose logging - truly cross-platform and cross-language with one specification, behavior for all How would it work? - devs can create a .env file if they want - devs load 'libconfig' into app, use it to load their configuration values during development. library can have default sources, and even set env vars or an object internally, so no code needs to be written to use it - in production, same code causes libconfig to look at cloud-native and other sources for configuration - when debugging, secret confidentiality is maintained, tracing communicates sources of configuration, what was loaded, from where, etc
- tamimio 2y ago> An attacker needs the DOTENV_PRIVATE_KEY And the attackers will be after this file not the .env anymore. It looks great nonetheless, especially the cross-language feature.
- boundlessdreamz 2y agoThis is similar to how Rails handles secrets - https://edgeguides.rubyonrails.org/security.html#environmental-security https://edgeguides.rubyonrails.org/security.html#environment... In Rails, the entire file is encrypted unlike here where only the secrets are
- cyberax 2y agoI _detest_ this kind of encryption. It's literally worse than useless. It makes life much harder during debugging, and it eventually leads to developers just storing the decryption keys locally. For this kind of encryption to work, you need to supply the decryption key from some outside system (e.g. via env vars, AWS SSM, etc.). And if it can supply the key, then why not just use it for other important secrets directly?
- gregwebs 2y agoI use tools that read secrets out of vaults on demand using existing infrastructure for key management. For AWS there is aws-vault.
- slt2021 2y agoit might be easier to just store and checkout a single decryption key that only devops people know, vs storing hundreds of secrets. while developers can move around their .env file across systems without worrying that they left plaintext secrets somewhere. also it allows adding new secrets without knowing decryption key - I think it is important for collaboration also most importantly: plaintext decrypted secrets are never stored on disk, and only kept in memory. I think it is also an improvement towards the regular doting
- cyberax 2y ago> it might be easier to just store and checkout a single decryption key that only devops people know, "Devops people know" means that the key must be some secret property. Or you need to use the key during the deployment artifact building pipeline, and then deploy the artifacts with clear-text secrets. > vs storing hundreds of secrets. Then serialize them to JSON or whatever. > also it allows adding new secrets without knowing decryption key - I think it is important for collaboration So basically, you want developers (who don't have access to prod) to add random properties that your peers can't see during the code review? Ok... Sorry, there's just no way the encrypted secrets in git are a good idea for general-purpose software.
- 2y ago
- sandstrom 2y agoI've started using Mise for some stuff at work. Haven't digged in a lot yet, but looks really promising. https://mise.jdx.dev/ https://mise.jdx.dev/ It handles task running (wipe local test db, run linting scripts, etc), environment variables and 'virtual environments', as well as replacing stuff like asdf, nvm, pyenv and rbenv. Still somewhat early days, tasks are experimental. But looks very promising and the stuff I've tried to far (tasks) works really well.
- ralgozino 2y agoI second mise, it's been a nice replacement for direnv, asdf and makefiles for my use case. Much faster, still compatible with the old configuration files when needed and all in one tool for the new projects. Awesome.
- renewiltord 2y agoI use asdf at work and mise at home. I only use it for runtime version management and it’s great!
- maleldil 2y agoSeconded. I changed from pyenv to mise because pyenv was slowing down my shell startup (probably the shims, which mise doesn't use by default), and I'm slowly using mise for more stuff. Right now, I'm using it to auto-turn on virtual environments and add project scripts to the PATH, and it works very well. I haven't felt the need to use it as a task runner yet, but that's probably because I'm used to having a bunch of shell and Python scripts in a `scripts` folder.
- mystickphoenix 2y agoAdd another vote for mise. For me it replaced asdf, pyenv, poetry, and direnv. Biggest thing for me is it _just works_:tm:.
- horse666 2y agoYes, also definitely a big vote for Mise. I’ve switched recently from asdf for managing language & tool versions and the ergonomics are much nicer (eg one command vs having to manually install plugins, etc., more logical commands) It’s also noticeably faster. Regarding the env vars features, a couple of relevant Mise issues around people trying to integrate env var secrets using SOPS, 1Password, etc. - https://github.com/jdx/mise/issues/1617 https://github.com/jdx/mise/issues/1617 - https://github.com/jdx/mise/issues/1359 https://github.com/jdx/mise/issues/1359
- stiiv 2y agodotenv has zero npm dependencies. dotenvx has 21, including a few I have never heard of. Is this really more secure?
- deleted 2y ago[deleted]
- caliwagon 2y agoRecent versions of node support env files directly, so you don't even need one dependency anymore. https://nodejs.org/docs/latest-v20.x/api/cli.html#--env-fileconfig https://nodejs.org/docs/latest-v20.x/api/cli.html#--env-file...
- iamsaitam 2y agoThis is quite a common remark when it comes to Javascript. I rarely see the same being made about Rust libs, which also rely heavily on external dependencies.
- stiiv 2y agoJustifiably! Supply-chain attacks have occurred via npm, and have been widely reported. A lack of oversight and lack of standard libraries are often cited as the cause. I don't know if it's a problem for Rust (or other platforms like Python, .NET, or Java afaik). As someone who primarily writes TypeScript to run in browsers and on node.js, this kind of threat requires an extra level of vigilence, and often nudges me toward writing my own things rather than importing them.
- usixk 2y ago[flagged]
- cimnine 2y agoI think it's good advice to not pass secrets through environment variables. Env vars leak a lot. Think php_info, Sentry, java vm dumps, etc. Also, env vars leak into sub-processes if you don't pay extra attention. Instead, read secrets from a vault or from a file-system from _inside_ your process. See also [1] (or [2] which discusses [1]). Dotnet does this pretty good with user secrets [3]. [1] https://blog.diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/ https://blog.diogomonica.com/2017/03/27/why-you-shouldnt-use... [2] https://security.stackexchange.com/questions/197784/is-it-unsafe-to-use-environmental-variables-for-secret-data https://security.stackexchange.com/questions/197784/is-it-un... [3] https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets https://learn.microsoft.com/en-us/aspnet/core/security/app-s...
- skissane 2y ago> Instead, read secrets from a vault or from a file-system from _inside_ your process. I’ve never liked making secrets available on the filesystem. Lots of security vulnerabilities have turned up over the years that let an attacker read an arbitrary file. If retrieving secrets is a completely different API from normal file IO (e.g. inject a Unix domain socket into each container, and the software running on that container sends a request to that socket to get secrets), that is much less likely to happen.
- deleted 2y ago[deleted]
- itchyouch 2y agoI used to store secrets in the FS, and was told the best practice was env vars. Now it's not env vars. What is it then?
- skissane 2y agoWell, I’d be the first to admit that we have a gap here, the solution that I personally would consider ideal doesn’t seem to actually exist, at least on the server-side. If we are running under something like K8S or Docker, then I think there should be some component that runs on the host, that provides access to secrets over a Unix domain secret, and then we mount that socket into each container. (The reason I say a Unix domain socket, is so then the component can use SCM_CREDENTIALS/SO_PEERCRED/etc to authenticate the containers). I’d also suggest not using HTTP, to reduce the potential impact of any SSRF vulnerabilities (although maybe that’s less of a risk given many HTTP clients don’t work with Unix domain sockets-or at least not without special config). (Can we pass memfd_secret using SCM_RIGHTS?) For desktop and native mobile, I think the best practice is to use the platform secret store (Keychain on macOS/iOS, Freedesktop Secret Service for desktop Linux, Android Keystore, Windows Credential Manager API, etc). But for server-side apps, those APIs generally aren’t available (Windows excepted). Server-side Linux often lacks desktop Linux components such as Freedesktop APIs (and even when they’re present, they aren’t the best fit for server-side use cases)
- nimishk 2y agoI don't think this is the best approach. I am building https://phase.dev https://phase.dev which lets you import secrets (.env), encrypt secrets (end-to-end encrypted with keys you control), sync them to other services/platforms (think AWS, GitHub, Kubernetes), and inject them into applications at runtime (e.g., phase run node index.js). Source: https://github.com/phasehq/console https://github.com/phasehq/console
- poopsmithe 2y agoWhat do you mean it's not the best approach? That's a little light on the details.
- hamasho 2y agoI want an option to manage all env in a single file using a TOML like format like this. [local] API_KEY=local-key API_SECRET=local-secret DB=postgresql://username:password@localhost:5432/database_name [production] API_KEY=prod-key API_SECRET=prod-secret DB=postgresql://username:password@prod-db:5432/database_name [staging] API_KEY=stg-key API_SECRET=stg-secret DB=$(production.DB) It makes it easier to update all env at once, compare, and share. It's not much help, but it helps me avoid a few annoyances. On an unrelated note, I always find it a real headache to keep the naming convention of the environments throughout the project. It always ends up like a mixed bag: * Juggling production/prod, staging/stg, and develop/dev, * Inconsistent placement of env, e.g. prod-myproject or myproject-stg, * Skipping env name sometimes, e.g. myproject-bucket for dev S3 bucket but prod-myproject-bucket for prod (though it's okay to emit env name for user facing places like URL), * Inconsistent resource sharing between envs, e.g. same S3 bucket for local and dev but different DB, or same Kubernetes cluster with different labels for dev/stg but different cluster without a label for prod. These inconsistencies often result from quick decisions without much thought or out of necessities, and everyone is too scared to fix them anyway. But it bothers me a lot and sometimes causes serious bugs in production. Fix: format
- nunez 2y agoYou can do that today with sops if you'd like!
- the_duke 2y agoWe implemented the exact same method for config encryption a year ago or so, using pub/private key auth and the same `encrypted:` prefixes for encrypted config values. This is a great tradeoff: easy way to share configuration, easy way to edit non-encrypted config values, reasonable security for the private values. Doesn't solve key rotation of course, but for small teams this is a great solution.
- treflop 2y agoThe only reason I use .env is because it’s dead simple and very obvious as to how it works to anyone. If now someone has to read docs to figure out how to configure the app, I’d rather have them read docs for some other safer and more powerful configuration scheme.
- pnt12 2y agoI've dealt with problems from python-dotenv and very much prefer it as a command than as a library. As an example, once I changed a .env fikr and unit tests started failing. Digging deeper into it, and lots of code was checking for .env to load its configurations, and would break without it. I'd prefer this not to happen, as our tests were executing based on outside, not version controlled, configurations. After removing dotenv as a library and using it only as a command, we were able to separate configuration and logic, and not have .env files affecting our unit tests - we simply ran the application with dotenv command, and the unit tests without.
- neonate 2y agohttps://github.com/dotenvx/dotenvx https://github.com/dotenvx/dotenvx
- deleted 2y ago[deleted]
- difu_disciple 2y agoI always thought highly of the approach used by https://www.npmjs.com/package/@strong-config/node https://www.npmjs.com/package/@strong-config/node Does dotenvx support secrets managers?
- tracker1 2y agoSince node v20.06, has built in support for --env-file=.env on load... as for local(ish) encryption and pushing them into source control, I don't like this at all. I'm fine using a vault or secret distribution from either the environment host (k8s) or ci/cd deployment. I do like to keep a .env.example that you can rename to .env and adjust as desired. I tend to have defaults for running a compose stack locally that close to "just works" as possible. I doubt I'd ever want to use this in practice.
- hooverd 2y agoPersonally, I like sops for encrypting my secrets.
- nunez 2y agodotenvx encryption goes a long way towards solving THE BIGGEST problem with dotenv; using multiple tools to ensure that secrets are protected. I wonder if dotenvx ensures that .env is in .gitignore and yells loudly if it is not. I encrypt my dotenvs with gpg, but that's hella esoteric and everyone shouldn't be forced to do that.
- daralthus 2y agoand .dockerignore
- TZubiri 2y agoImporting a set of library and dependencies to handle reading a plain text file poses more risks than just leaving the file unencrypted. You don't need to encrypt your keys, with what keys are you going to do so? Will you encrypt those? if someone is in your server you are pwned anyways. It's ok if you identify yourself as a cybersecurity dude and hold a cybersecurity role and you need to justify your livelihood. But do it in a way where you don't bother people. It's ok if you bother devs, but then you go on and bother users with 4FA, 5 rule passwords, systems that can't answer subpoenas because you have encrypted your sense of self. When you are improving security at the expense of every other variable, that's annoying, but when you keep "improving security" at the expense even of security, is the point where people will start ignoring and hiding shit from you
- NegativeK 2y ago> if someone is in your server you are pwned anyways. This is false and also a symptom of an all-or-nothing approach to cybersecurity, which isn't feasible in the real world.
- TZubiri 2y agoI suppose they could have read only access to the filesystem and read the api keys, like through an http server
- qweqwe14 2y agoSorry but it is largely all-or-nothing in this case, if someone has access to the user the app runs as, you are screwed. It doesn't matter whether you use env vars or files. I'm assuming the parent intended to say "if someone gained access to your user you are pwned anyways", which is true, unless you actually go to the effort of storing the secrets securely using OS-provided mechanisms. Env vars are not that. > which isn't feasible in the real world Well of course it isn't, how would you justify those sweet cybersecurity experts' paychecks otherwise? Not saying cybersecurity isn't important, but there's way too much snake oil in the industry nowadays (always has been?).
- stephenhuh 2y ago
- Aerbil313 2y ago[flagged]
- swedonym 2y agoHuge fan of dotenv, excited to try this out!
- daralthus 2y agoGOAL: To be able to commit all your envs to git. This is the only goal and this tool archives it. In the simplest way. While keeping you as secure as you were before, manually setting envs on heroku, railway, aws, jenkins etc. GitOps FTW
- daralthus 2y agoCan you do safer? Yes, yes you can with a secrets management service (e.g.: Hasicorp Vault). Is that way more complicated to setup in all envs? Oh yes, yes it is.
- frithsun 2y agoThanks, but I would rather go with the imperfect setup that I understand than an allegedly perfect setup with dozens of third party dependencies that I don't understand. Doubly the case now that env is natively supported by node now.
- rednafi 2y agoWritten in JS; I think I’ll pass.
- drchickensalad 2y agoYour "a single gitignore append" command overwrites existing .gitignore files. It should be `>>`
- Aeolun 2y agoIt doesn’t have Typescript types!
- blacksoil 2y agoCan someone help enlightening me. In terms of preventing leaks, since we still need to ensure that the .env.keys doesn't leak, wouldn't effort still be the same? The ability to use arbitrary filename for.env is quite nice though!
- nightpool 2y agoThe idea is that the private key is stored outside of your configuration directory (e.g. in your OS's keychain), so your dotenv file can contain encrypted key values without leaking the value itself.
- kodeninja 2y agoHow would this work with application-specific Intellij Run/Debug configurations? Would this require switching to a "Shell Script" configuration, thereby losing debugging capability etc?
- clord 2y agoEnv vars over-share and files depend on local permissions. We should have a capabilities -like way to send secrets between processes. e.g., decrypt and expose on a Unix socket with a sha filename that can only be read from once, and then gets torn down. Share the file name, target can read it and immediately the secret is now at-rest encrypted. Encryption based on config containing a whitelist of ssh public keys and what they can access, sort of like age.
- bhawks 2y agoYes and now we have to manage the identities of processes to ensure they are entitled to given capabilities. Also any system as described needs security audit and analysis to truly understand it strengths and weaknesses (or glaring compromises). Alternatively - secrets via environment vars weaknesses and mitigations are well understood.
- panzi 2y agoWait, it's also doing command interpolation? I missed that. Where is the code for that? I thought it uses dotenv-expand for interpolation, which can't do commands. dotenv-expand is already a bit meh, because of how it resolves the variables after parsing the dotenv file. Meaning you can't have a verbatim single quoted string and also you can get a stack overflow doing this: A=$B B=$A Anyway, I hope they don't do command interpolation on top of that (like Ruby dotenv does), because then you can inject code via environment variables (like in the Ruby version). I recently looked into various dotenv implementations just for fun. They're all different. No unified syntax at all. A lot don't do proper parsing either, but just use some regular expressions (like this one), which means they just skip over what doesn't matches. I started to document all the quirks I could find and wrote my own dotenv dialect just for fun. Nobody use it! Anyway, here it is: https://github.com/panzi/punktum https://github.com/panzi/punktum Direct link to the quirks of the JavaScript dotenv implementation: https://github.com/panzi/punktum?tab=readme-ov-file#javascript-dotenv-dialect https://github.com/panzi/punktum?tab=readme-ov-file#javascri... I've also tried to write a parser compatible to JavaScript dotenv (no x) in C++: https://github.com/panzi/cpp-dotenv https://github.com/panzi/cpp-dotenv
- sampli 2y agoBased on my skim, this doesn’t really solve anything? The private key to decrypt is still stored on machine in a similar place? All this is doing is obfuscating?
- skeledrew 2y agoI've recently taken a simpler approach to handling secrets in .env files. Since I use autoenv and conda venvs for everything, I persist secrets outside all projects in appropriately-named files, so including them in a .env becomes similar to `source $HOME/.secrets/work__aws_access`. Also makes them easier to manage across projects.
- dagss 2y agoSomething I have done for secrets is use a syntax in environment variables to tell the process to go a key vault for the secret. So we can have FOOPW=pw1 when testing locally, but FOOPW="{vault1:secret1}" in production. Env vars are processed simply by running a regex with callback that fetches secrets from vaults. This is quite flexible and has the advantage of being able to inject the secrets in the same place as other configuration, without actually having the secrets in environment variables or git etc (even encrypted)
- pak9rabid 2y agoHah! I've done something similar. In my case, I could have something like this in my .env file: SOME_CONFIG_OPTION = @AWS::some_config_option And I've written a config library that knows that when a config value starts with `@AWS::' it needs to resolve the config option to an actual value by reaching out to AWS's Secrets Manager service and looking it up there, in which case it receives the value and caches it locally so that subsequent references to this configuration option don't require an additional call out to the cloud. It works surprisingly well.
- globular-toast 2y agoWait, people use the .env file for secrets?! I never even looked into this but just assumed this was a convenience for local dev to hold a local non-secret app config? In production you'd load the env from a secrets store like what kubernetes has or aws has for ec2 instances. You shouldn't ever have those secrets on your local machine... Because they are secret.
- sneak 2y agoThis seems to encourage committing encrypted secrets, which is a bad idea. Configuration and code should be in separate repositories. Secrets should be protected elsewhere. The correct fix for “it’s too easy to accidentally commit .env files with secrets” is to not function (panic/throw) if there isn’t a suitable .gitignore/.dockerignore, not a specialized cryptosystem for .env files. This just creates a different problem. I simply use an envdir outside of the project and update all my run scripts to use “envdir $CONFIG_PATH <whatever>”. Simpler and safer.
- jbverschoor 2y agoYet another problem already solved 25 years ago by the mighty Sun in the J2EE spec.
- yashbindal 2y agoIntersting
- politelemon 2y agoI'm not comfortable that this tool is able to make HTTP requests, IMO it ought to be completely offline and not perform network operations. I did a search for requests and found some results pushing to and pulling from a 'hub'. But I couldn't figure out what the hub refers to.
- Alifatisk 2y agoSo with this, I have to prefix every executable with dotenvx in order to utilize the env variables? Can’t I somehow do this in the script itself so “ruby index.rb” is enough? I know I’m only saving a couple of characters in the command line but I’m asking out of curiosity.
- wodenokoto 2y agoA lot of people here are saying that a vault is preferable to this, especially for secrets. Is there a good primer on using vaults? I know how to query and insert into Azure Key Vaults, but architecting around it is unclear to me. Things that come up for me: - As (azure) key vaults don't support per secret access rights, where do I store secrets between deployments? - Should I store connection strings to cloud resources, or just ask the resource for the connection string at deployment time (for Azure, a cloud function pretty much needs a connection string for most basic things. They say they are moving away from this but ...) - A security warning is send if a key is accessed more then x/times per hour. Does that mean I should pull in the key from vault at deployment? Cache it after first call during runtime? - Most of our 3rd party vendors gives us 1 and only 1 key. How do I manage that key between development, production and several developers? Right now we mostly forward the e-mail from the vendor with the key ...
- PaulHoule 2y agoMy beef with it is that it's written in Javascript whereas what it does is so simple that they should just code it up in Rust or Go and be done with it, particularly when it could be packed up as a tiny binary that doesn't require you to install Node, Python, the JVM or any other runtime or library.