DEV Community

Loading environment variables in JS apps

Maxime on August 04, 2018

How to store and consume environment variables for local development APIs and third-party integrations require developers to use configu...
Collapse
 
asamolion profile image
Muhammad Osama Arshad

Hi there, nice article.

Just have a quick question. Does the dotenv script load the entire .env file into the client side?

If that's the case then wouldn't that expose sensitive data such as DB password etc?

Collapse
 
fabiorosado profile image
Fabio Rosado • Edited

This might be silly but I was wondering exactly the same thing. If you can do console.log(process.env); I wonder if the values are automatically replaced by environment variables perhaps?

--EDIT--
I went ahead and read the link to the 12-factor app and this is exactly what happens. The values are replaced by environment variables with each deploy.

The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard. - The Twelve-factor App

Collapse
 
asamolion profile image
Muhammad Osama Arshad

Very cool. Thanks for taking the time to answer.

Collapse
 
deammer profile image
Maxime

Hi Muhammad! The entire .env file is indeed loaded, so all the secrets (including database passwords, in your case) will be exposed on the client, if that's where your app is running. This would obviously be a huge problem in a production environment, but my use case was centered around local development.

Security depends heavily on your deployment pipeline and the kind of system you're building, and I don't want to go too deep on that topic in a comment, but I'll leave you with two things:

  1. If you're developing a client-side app, it should be making calls to an API, not a database. This way, even if the API key is leaked, you can control security by making the API read-only or having a strict CORS policy.
  2. You could use the code below to make sure your client-side app doesn't expose secrets:
if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config();
}

Hope this answers your question!

Collapse
 
asamolion profile image
Muhammad Osama Arshad

I see. I was thinking of using this in production in my current client's app. Thanks for pointing this out.

Dodged a bullet there.

Collapse
 
rannn505 profile image
Ran Cohen

Hi Everyone,

Firstly, I'd like to commend @deammer for this insightful article.

Reading through the comments, I noticed some concerns regarding handling of secrets and configuration deployments. As your projects scale, complexities with managing more code, services, and environment variables are bound to increase. That's where a third-party tool can come in handy.

I recommend considering a tool like Configu for managing your app settings. It's an open-source, language-agnostic solution that streamlines configuration management. By using Configu, you can alleviate the burden of dealing with raw-text based files and orchestrating configuration data across various formats during build, deployment, or runtime.

For more insights, feel free to check out my article that dives deeper into this topic: Configu - Unleashing the Power of Configuration as Code

Happy coding!

Collapse
 
qm3ster profile image
Mihail Malo

So, the most interesting part is missing:
How do I actually shove some .env files into the deployment environment?
Are we talking about functions? Container images? VM images? Persistent VMs?

Collapse
 
deammer profile image
Maxime

Hi Mihail! This article is focused on local development, in part because there are countless ways to execute deployments.

For instance, tools like Travis, Heroku, and Netlify provide a UI that lets you set up environment variables. If you're using a VM-like environment like EC2 or Digital Ocean, you can actually upload a .env file directly. If you're using a container system like Docker, you can use Compose or config arguments to set environment vars.

Hope this helps!

Collapse
 
qm3ster profile image
Mihail Malo

So, using the dotenv module is essentially the local version of those managed environments' ENV configs?
Then, perhaps, the best way to use it is node -r dotenv/config your_script.js, and only include it in devDependencies so it's not present at all in production?
...but in that case it's not very different from just putting a cross-env at the start of your development script.
I guess I still don't entirely understand what unique niche dotenv is the best fit for.

Thread Thread
 
misterhtmlcss profile image
Roger K.

Hi Mihail, have you written anything about how you go about protecting while using your secret keys? I'm interested to learn more and if you have then please post a link. These kinds of nuts and bolts articles are in such dire need from my point of view.

Thread Thread
 
qm3ster profile image
Mihail Malo

Well, so far as protecting secrets, at the moment I believe that these are indeed best set as environmental variables of the deployment environment.
I know some people use git hooks that test that they aren't committing any secrets, but I believe these are brittle and only give a false sense of security.
A rule that seems to work for me is - if you want to make sure something is never committed, don't put it in the project directory. Don't test with it.

But then there's still the app's responsibility of not sending the secrets to any users.
Corollary: Don't rely on this as a way to protect the secrets from malicious developers or even accidental disclosure. If they can get code into production, they can compromise any data available in the production environment. Even if all deployment goes through CI from a protected branch, all you get is blame a long time later.
Hence, all secrets must have the minimum permissions possible. For example, every service should have its own database login/connection string. Not for permissions alone, but so that it can be easily replaced when compromised.
Another example (although not usually provided through ENV since they are reissued at runtime) could be asymmetric JWT algorithms, where most services can only verify the token but not issue it.

Thread Thread
 
misterhtmlcss profile image
Roger K.

Thank you! I can't read input like this often enough. It really helps me. I wish experienced devs talked more about it, since it's so key to delivering a basic professional experience

Collapse
 
kyleparisi profile image
Kyle Parisi

Additional tip

dotenv.config({ path: ".env" });
// Set any missing with defaults
dotenv.config({ path: ".env.example" });
Collapse
 
trystonperry profile image
Tryston Perry

Thank you! I've been trying to figure this out for a while and couldn't find a resource on how to do it.

Collapse
 
deammer profile image
Maxime

Glad you found this useful!

Collapse
 
rmoskal profile image
Robert Moskal

I don't think there's any harm in keeping development secrets under version control in many, many cases. Especially when you are using something like compose. It speeds up the onboarding of new developers. Production secrets are another matter.

Collapse
 
obstschale profile image
Hans-Helge Buerger

Great tutorial. Thx for sharing 👍

Collapse
 
sd031 profile image
Sandip Das

good read before going to sleep :)

Collapse
 
ismailpe profile image
Ismail PE