question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Document best practices

See original GitHub issue

I struggle a long time to understand this 12-factors point about env-powered configurations.

I’ve read through all issues of this and the mirror Ruby repos. Through a number of stack overflow threads.

The final picture is still obscure to me. Maybe it’s really a wrong direction (if it causes so much confusion and debates between people) or maybe everyone needs a better explanation of the entire workflow.

I surely see a number of benefits in the env approach. Cross-language / cross-platform way of app configuration being the most vivid. But I also see drawbacks and I’m yet to find some comparison table which would ensure me that benefits are bigger in the common case.

Here are the questions from the top of my head:

  1. Where to put default .env to copy at installation step? Should we exactly symlink or copy this file?

  2. If answer to 1) is copying: do you pass variable name to replace NODE_ENV value in destination .env at installation step?

  3. How exactly do you set different .env for testing? At what place it occurs? There are multiple ways to implement this. Which one is recommended?

  4. Does the lack of global fallback values cause practical issues (your personal experience)? process.env.xxx || <something> is more or less a DRY violation… Most config systems provide an option to set global fallback value for every config option. Did anyone ended implementing his own custom solution to cover this case?

  5. Does string-only config cause practical issues (your personal experience)? Most config systems use js files with native types (and highlighting!) available. Did anyone ended implementing his own custom solution to cover this case?

  6. Does the lack of a syntax for required config cause practical issues (your personal experience)? Most config systems provide this feature throwing exceptions in a “broken environment”. Did anyone ended implementing his own custom solution to cover this case?

  7. Configuration in a frontend (client, browser)…

Personally, I find such blurry conventions undermine the whole “it’s more obvious” promo declaration. It’s hard to call something “superior” when it’s just about tradeoffs and personal preferences. I’d prefer to be wrong though.

[Added]: I already start to discover issues with 4) and 5). Most libraries expect boolean config values to be boolean. So we’re going to repeat not only default values but also type conversions (or string comparisons) in every place it will be used…

port = parseInt(process.env.HTTP_PORT) || 80 // in every place
...
port = parseInt(process.env.HTTP_PORT) || 80 // in every place

useEtag = process.env.HTTP_USE_ETAG == "true" ? true || false // in every place
...
useEtag = process.env.HTTP_USE_ETAG == "true" ? true || false // in every place

😞

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:4
  • Comments:10 (3 by maintainers)

github_iconTop GitHub Comments

5reactions
maxbeattycommented, Jun 18, 2015

Thanks for the questions, Ivan. I’ll do my best to answer and maybe a wiki page can come of this thread.

Where to put default .env to copy at installation step?

You should put it in the root of your project. If you run your app as node index.js, your .env file should be in the same directory as index.js. This is customizable with the path option, but by default, we look for it in the directory you’re executing node from.

Should we exactly symlink or copy this file?

Either works. This is very dependent on your deploy process. Personally, we have used symlinks with a lot of success. We keep multiple releases so we can rollback bad deploys. We symlink the .env file for the project to each release directory. Here’s an example directory structure (truncated for clarity):

$ pwd
/home/my-app
$ ls -al
drwxr-xr-x .
drwxr-xr-x ..
-rw-r--r--    .env
drwxr-xr-x release-1/
drwxr-xr-x release-2/
$ ls -al release-2/
drwxr-xr-x .
drwxr-xr-x ..
-rw-r--r--    .env -> ../.env
-rw-r--r--    index.js

do you pass variable name to replace NODE_ENV value in destination .env at installation step?

We set this by hand in the .env file just like any other variable. Preparing the file is, again, very dependent on your deploy process. The sky is the limit for automation.

How exactly do you set different .env for testing? At what place it occurs? There are multiple ways to implement this. Which one is recommended?

I see an environment as being a combination of software and hardware (and that’s a very loose definition). If you’re running your app on your laptop, that is one environment. If you’re running tests on Travis-CI, that’s another environment. If you’re running tests on your laptop and want to use a different database for integration tests, I would suggest using a VM or Docker containers to separate. Trying to use the same environment (i.e. your laptop) as different environments (development and testing) is not a best practice.

Does the lack of global fallback values cause practical issues (your personal experience)?

No, having a misconfigured environment (incomplete .env), to me, is at the same level as not having your database running. Your app’s environment needs to be prepared to run and that includes a complete .env file.

Does string-only config cause practical issues (your personal experience)?

Nope, I’ve never had a type issue. Passing string ports to express, hapi, sequelize, and mysql have worked just fine in my experience. I avoid boolean flags and instead opt for “only do this in production”

if (process.env.NODE_ENV == 'production') {
  // turn on something critical
}

If you need to use boolean environmental variables, I’d recommend not setting it in your .env for environments where it would be false. Then, it will evaluate to false because it will not be set on process.env

Does the lack of a syntax for required config cause practical issues (your personal experience)?

I don’t understand this question. Will you elaborate?

Configuration in a frontend (client, browser)…

First, be careful you’re are not sending sensitive information to the client. Stripe’s publishable key is a good example of a environmental-dependent value that you would load on the server and pass to the client.

  1. load environment variables on the server
  2. render an environmental variable in your server-side HTML in a script tag
  3. reference that variable as needed in client code

It’s hard to call something “superior”

Please let me know if dotenv has ever referred to itself as “superior”, as that is not our intent, so I can correct it. TMTOWTDI when it comes to configuration. I’ve personally had a lot of success and enjoyment using dotenv. We’re always looking to improve but will also stick to our guiding principles.

4reactions
justindeguzmancommented, Dec 25, 2016

Just to clarify the following question for future readers, which also confused me for a bit (and I think the README only lightly touched on):

“How do you deal with multiple .env files for dev, prod, etc.?”

This article clarified it. It basically says the reason you should only have one .env file is because Heroku, AWS, etc. should be managing your production variables for you. Your own .env file should only be for your local environment.

With that being said, lots of products are encouraging environment variables to be checked in to your repo in some form. Whether or not to do so is really a question about practicality and how much you want to adhere to the 12-factors. See Serverless or CircleCI for example.

Read more comments on GitHub >

github_iconTop Results From Across the Web

10 Tested Document Management Best Practices You Must ...
10 Document Management Best Practices · 1. Setup a clear strategy · 2. Manage documents in a single location · 3. Keep a...
Read more >
11 Best Practices for Document Management - DocuWare
1. Start with goals and develop key metrics · 2. Prioritize automation of simple and frequently used business processes · 3. Improve paper-based ......
Read more >
9 Document Management Best Practices You Must Know
1. Setup Rules or Positions · 2. Choose a Good Document Management System · 3. Proper Structure of Files and Folders · 4....
Read more >
Share Best Practices among Colleagues - MPUG
Not only does documenting best practices call attention to a job well done and identify the expertise that exists within your project team,...
Read more >
Documentation Best Practices | styleguide - Google
Documentation Best Practices · Minimum viable documentation · Update docs with code · Delete dead documentation · Prefer the good over the perfect...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found