Node JS to load dotenv with forever - node.js

I would like to ask if anyone know how to run forever that can load .env file.
Currently if we run forever start app.js, process.env.foo become undefined.

TLDR, You need to add the --workingDir path to your cronjob line.
forever -c "node -r dotenv/config" --workingDir app-workdir-path start app.js
Many previous answers but none of them really solve this specific use case.
To run forever with dotenv you'll need to do two things.
First is we need to use dotenv's preload feature, meaning we need forever to pass a node parameter to the process. we can do it by using the -c COMMAND flag forever has.
The second thing is related to how the dotenv package works. here is snippet from the source code:
let dotenvPath = path.resolve(process.cwd(), '.env')
What does process.cwd() do?
The process.cwd() method is an inbuilt application programming interface of the process module which is used to get the current working directory of the node.js process.
Meaning dovenv package want's to load the .env file from the working directory. so to solve this issue we can use forever's --workingDir flag to specify the actual working directory of the process.
And the final command will look like this:
forever -c "node -r dotenv/config" --workingDir app-workdir-path start app.js
Where app-workdir-path is the absolute path to the project directory.

What worked for me was to specify the full path:
require('dotenv').config({ path: '/opt/api/.env' });

You can use dotenv package for this purpose. On your app entry, do this
require('dotenv').config({ path: '.env' })

If you have added .env file in root directory of your project then you can use like this
require('dotenv').config()
Or if you created your file .env with different location then in your code use
require('dotenv').config({path : '/your/path/.env'})

I found your question and had the same issue. I don't think dotenv works with forever - At least not that I was able to get working. However, I think there's a workaround that you could employ. I was able to specify environment variables on the command line preceding the forever command, and forever passed those environment variables to my node app.
~$ ENV=production forever start yourApp.js
For more information about specifying environment variables on the command line, checkout this Stack Overflow question.

I've had this issue with multiserver forever config.
You should include --workingDir parameter pointing to the root of your project directory in case you've included .env file in your root and using dotenv
Example:
Flexible config with minimum "hard coded" values
.env placed in root directory
"dotenv" used in form of dotenv.config()
Code for multiserver config in case of one server:
const fs = require('fs');
const path = require('path');
let foreverConfig = [
{
uid: 'scheduledJobsServer',
append: true,
watch: true,
script: 'scheduledJobsServer.js',
sourceDir: path.join(__dirname, '/server'),
workingDir: path.join(__dirname)
},
{
uid: 'mainServer',
append: true,
watch: true,
script: 'server.js',
sourceDir: path.join(__dirname, '/server'),
workingDir: path.join(__dirname)
}
];
try {
fs.writeFileSync(
path.join(__dirname, '/foreverConfig.json'),
JSON.stringify(foreverConfig),
{ encoding: 'utf8' }
);
let consoleMessage = 'Init script success';
console.log('\x1b[42m%s\x1b[0m', consoleMessage);
} catch (e) {
console.log('Init script error:', e);
process.exit(1);
}
Then run forever start foreverConfig.json

Sometimes you have to call the node script from another directory. For instance, when running cron jobs. Here is what you can do:
cd /path/to/script/ && /usr/bin/forever start /usr/bin/node script.js
Now the .env file will load.

The easiest command for me is
dotenv -e .env forever start build/index.js

Related

NodeJS not recognizing .env file

I have like 5 NodeJS services running, but I have a problem in one of those.
This is the nodemon.json file:
{
"watch": ["**/*.ts"],
"ext": "ts,json",
"ignore": ["./test/*.ts"],
"exec": "node -r ts-node/register -r dotenv/config Index.ts dotenv_config_path=$(pwd)/.env",
"env": {
"NODE_ENV": "development"
}
}
It's the same as the rest of services. When I run npm run dev I got error messages depending on which value is taking from the .env file, example:
const LOCAL_CONFIGURATION = {
PORT_APP: 8082,
MONGODB: {
SERVER: process.env.MONGO_DTE,
AUTH: {
auth: {
password:process.env.MONGO_PASSWORD,
user:process.env.MONGO_USER
}
},
},
MS_NOTIFICACION: "http://localhost:8089/notificacion",
ELASTIC_PATH: process.env.ELASTIC_PATH,
...COMMON,
};
The first error message is:
ConfigurationError: Missing node(s) option
That message is produced because it's not reading the value from process.env.ELASTIC_PATH, but if I put a hardcoed value like "http://with.the.correct.url" and it tries again to run, I get another error:
Error: Credentials must be provided when creating a service client
That error is because it's trying to read password:process.env.MONGO_PASSWORD and user:process.env.MONGO_USER
etc, so, there's a problem on reading the .env file. I know that .env file has those values, and the file is in UTF-8, without quotes, etc. The .env file is the same file as the other services, it works ok in the rest but I don't know why is not getting read here.
Any idea?
EDIT:
Plus, I put a console.log(process.env); in config.ts file and it shows values like this:
But there's no values from the .env for example, there in the picture there's a value called COMPUTERNAME so if I put console.log(process.env.COMPUTERNAME); I get: IBM-NOT87
Why is not getting the .env file?
Seems like you need to require/configure dotenv. Docs:
As early as possible in your application, require and configure dotenv.
require('dotenv').config()
To further expand on #JBallin answer
you should use this on your app.js
Or if that does not work then you will need to explicitly add it to the file you are wanting to use those Variables
Sharing image, as its sometimes easier to see expanded
code here =>
require('dotenv/config') // require the dotenv/config at beginning of file
const express = require('express')
const mongoose = require('mongoose')
require('dotenv').config({ path: "./sample.env" });
In the file you are using environment variables,
As early as possible, require the "dotenv" and in the config() method, specify the path of the .env file, even if it in your root directory or the same directory where node starts.
The code for requiring and specifying file in the same directory is in the first line in the answer.
Also, for further reading 📖 , you can visit https://github.com/motdotla/dotenv#path
You cat try this.
-> npm i dotenv
and in code add this piece of code
require('dotenv').config({
path: 'your path here'
})
Install dotenv package
npm install --s dotenv
And add this require("dotenv").config(); in index.js/ts file.

nodejs __dirname is a dot when I try to execute a script directly in package.json file

Here is a chunk of my package.json file:
{
...
"scripts": {
"run-test": "node -e 'require(`my-test-lib`).whichPath(__dirname )'",
},
...
}
When I read my function param into the 'test' script, it is a simple dot . :-s
I thought that __dirname was always absolute, but it's not the case...
I've used process.cwd() for the moment, but I'm curious why this is not working. Have you got a clue ?
While I was searching, I found this question that is related to the subject and I found relevant, but it has no answer.
__dirname
has a different value depending on which file is invoked it in, whereas.
#laggingreflex mentioned in comments: "The docs describe __dirname to be "The directory name of the current module". Since you're using -e flag to execute the code, no module is actually loaded, so it'd make sense not to expect an actual path from it"
process.cwd()
always returns the same value, which is the absolute path of where you started the Node.js process (eg., $ node index.js).
console.log(__dirname); // /project
console.log(process.cwd()); // /project
const test = require('./module');
/* module code
console.log(__dirname); /project/module
console.log(process.cwd()); /project
*/

Why are my custom process.env not working within dotenv?

Learning that it is a bad practice to include API secret keys I've done some research and trying to learn how to create custom process.env.
After reading:
Node.js Everywhere with Environment Variables!
How to set NODE_ENV to production/development in OS X
How to set process.env from the file in NodeJS?
dotenv file is not loading environment variables
I'm trying to set an env file locally based on process.env.NODE_ENV. The application would be hosted on Heroku and in my .gitignore I have dev.env but when I try to use dotenv locally I'm getting an undefined. I have set the environment locally with export NODE_ENV=development in my terminal. When I run the command npm start or nodemon both return undefined but in env.js I get Testing for: development, example:
nodemon
[nodemon] 1.19.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node app.js`
Testing for: development
undefined
Here is what I have:
app.js:
const keys = require('./config/env')
return console.log(process.env.PORT)
config/env.js:
const env = process.env.NODE_ENV
console.log(`Testing for: ${env}`)
try {
switch(env) {
case 'undefined':
Error('Environment undefined, if local in terminal: export NODE_ENV=development')
break
case 'development':
require('dotenv').config({
path: './dev.env'
})
break
case 'production':
require('dotenv').config({
path: './prod.env'
})
break
default:
Error('Unrecognized Environment')
}
} catch (err) {
Error('Error trying to run file')
}
config/dev.env:
## Port number to run Application
PORT=4321
but in app.js when I test with return console.log(process.env.PORT) or return console.log(keys.PORT) they both log undefined, why? I seem to be doing something wrong in env.js when using dotenv.
To clarify I'm not even pushing to Heroku yet and prod.env will be validation. If there is a better approach please educate me.
I've figured where I was going wrong after re-reading the documentation regarding path, example:
require('dotenv').config({ path: '/full/custom/path/to/your/env/vars' })
After changing:
case 'development':
require('dotenv').config({
path: './dev.env'
})
break
to:
case 'development':
require('dotenv').config({
path: `${__dirname}/dev.env`
})
break
it works. So my error was a scope issue. No need to set const keys so just using require('./config/env') I can access any custom processes, example:
process.env.CUSTOM
or in this case it would be:
process.env.PORT
from app.js
Hi at first use switch(env.trim()), then change the path value path: './config/dev.env'. Goodluck.
You are getting this error because you need to set those environment variables, as we don't have .env files there whereas on dev server dotenv set it for you using your .env file.
You need to set those variables either via the web interface or the heroku CLI.
This heroku doc will help you.
Heroku doesn't run on dotenv.
It has something called "Config Vars" within the Settings page of the given Heroku App:
For example
For your example, if the code wants to access: process.env.NODE_ENV, you would set a new Config Var within your Heroku Settings page of the given app, and call it NODE_ENV. Set the value you want, and press save. Voila. Done.
The added value of dotenv is usually for testing on your local machine.
if you are seeing the variables using echo $var but process.env.var is giving you undefined, then make sure you have that export keyword when creating the variable.
export var="value"

Toggle between multiple .env files like .env.development with node.js

I want to use separate .env files for each mode (development, production, etc...). When working on my vue.js projects, I can use files like .env.development or .env.production to get different values for the same env key. (example: in .env.development: FOO=BAR and in .env.production: FOO=BAZ, in development mode process.env.FOO would be BAR, in production i'd be BAZ).
I'm working on an Express server and want to use these same kinds of .env files to store the port, db uri, user, pwd...
I know I can edit the scripts in package.json like this:
"scripts": {
"start": "NODE_ENV=development PORT=80 node ./bin/www",
"start-prod": "NODE_ENV=production PORT=81 node ./bin/www"
}
but this gets messy when using multiple variables.
I've tried using dotenv but it seems like you can only use the .env file. Not .env.development and .env.production.
Can I use the dotenv package or do I need another one? Or could I do this without any package at all?
You can specify which .env file path to use via the path option with something like this:
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` })
The above two answers are both slightly off. let me explain. Answer from KyleMit below is missing ./ to indicate current directory.
the ./ indicates current directory in Node.js. The Second . prior to env indicates a hidden/private file. Thats why in KyleMits answer if the env file was not in the root of the PC it would never find it. The simplest way to do it in my opinion is to add a ./
this says "hey computer look in my current directory for this file".
//look in my current directory for this hidden file.
// List hidden files in dir: ls -a
require('dotenv').config({ path: `./.env.${process.env.NODE_ENV}` })
//I reccomend doing a console.log as well to make sure the names match*
console.log(`./.env.${process.env.NODE_ENV}`)
I'm using the custom-env npm package to handle multiple .env files. Just put this at the top of your code:
require('custom-env').env();
and it will load environment variables from the file .env.X, where X is the value of you NODE_ENV environment variable. For example: .env.test or .env.production.
Here is a nice tutorial on how to use the package.
From answers from above:
This is the final result that worked for me.
.env.dev file in src dir.
import path from 'path';
dotenv.config({ path: path.join(__dirname, `./.env.${process.env.NODE_ENV}`)});
For Typescript:
import dotenv from 'dotenv'
dotenv.config({ path: `.env.${process.env.NODE_ENV}` })
Install the dotenv package:
npm install dotenv
We need to get the .env file name based on NODE_ENV, it might be undefined, set default to development:
const envFileName = `.env.${process.env.NODE_ENV || "development"}`
Import the dotenv package and use it:
dotenv.config({ path: envFileName });
The official doc of dotenv does not recommend having multiple .env files.
"Should I have multiple .env files?
No. We strongly recommend against having a "main" .env file and an
"environment" .env file like .env.test. Your config should vary
between deploys, and you should not be sharing values between
environments."

process.env.SOME_KEY is undefined

How do I set the value of process.env.SOME_KEY=some value in the operating system and then read it in my node application? I am running on Windows.
I tried these steps:
SET SOME_KEY=abc
npm start
But when I try to read process.env.SOME_KEY, I am getting "undefined".
How do I set a env value and how do i read that in my code?
Try this: https://www.npmjs.com/package/dotenv
All you need to do is add a .env with your environment variables, and require('dotenv').config() as soon as you can in your application (the script called by npm start would be a good place)
SOME_KEY=`${abc}` Fixed it for me.
The npm module cross-env was made exactly for this purpose. The way you set an environment variable is not same across all the OSes. cross-env solves this.
Else, you can also try dotenv that solves this with a .env file.
You can also do this at the very basic level:
process.env.SOME_KEY = "somevalue";
Add this in index file
require('dotenv').config({path: path.join(__dirname, '.env')});
const path = require('path');
require('dotenv').config( { path: path.join(__dirname, 'variables.env') });

Resources