process.env.PORT is undefined (in LinuxCloud environment) - node.js

I've been developing a nodejs app on C9 for some time and now I'm trying to make a copy of it on my remote host. So far, in the new environment node app.js works in the console but I am unable to view the website in my browser.
It seems that it is a port issue.
My app.js file goes like this :
var express = require("express"),
app = express();
(...)
app.listen(process.env.PORT, process.env.IP, function(){
console.log(process.env.PORT);
console.log("The YelpCamp Server Has Started!");
});
In the C9 environment, the log tells me that process.env.PORT is 8080. But in the new environment, the log tells me that process.env.PORT is undefined.
How can I fix this ?
This is similar to this older question except that my remote OS is Linux not Windows. The answer to this question says that one should "modify the web.config file", but I couldn't find it on my remote host and I'm not sure it works the same way under Linux and under Windows.

process.env variables are set by the "Environment". Basically, they act as access to your systems environment variables. When trying to access process.env.PORT it'll return undefined if you've not setup that environment variable in the shell that you're trying to run your system.
You can set the environment variable up before you run node app.js with the following.
$ PORT=8080
$ node app.js
In this case we set the environment variable within the existing shell, then we call node with the app.js file. Environment variables are passed from parent processes into processes they start, if you run those two in sequence, you'll be setting up an environment variable within the current shell, and node will then receive that when it starts up (along side all other environment variables).
To see all environment variables avalible to the existing node process you can run console.log(process.env);.
This will be the same for process.env.IP as well.
Side note: C9 and other similar environments often have a lot of pre-set environment variables. This is why it was available on C9. The same is true for Heroku as well, this is because their system must dictate the port your service should use so that their load balancers / reverse proxies can be pre-configured for that port.

I ran into something similar and ended up providing a default port number if one couldn't be read from the environment.
const PORT = process.env.PORT || 8080;
app.listen(PORT, ...)

After deploying your node project files, you'll need to make sure any env variables are also transferred.
1. Manually copy-paste env variables
From the original host config to the new host config. Use the dashboards on either end. Simple and secure.
--- or ---
2. Manually transfer .env file from project root
(Not recommended for production environments) Node projects often have a .env file in the root, which is commonly excluded from file transfers (for obvious security reasons). You'd need to make sure the new host also has the identical .env file in root. For production environments, this is usually not desired for security reasons, and it's better to use option #1.
Projects using this method are likely using the dotenv package which detects .env and makes the parameters available to your app. It's mainly for development convenience.

Related

How to see process.env after starting server

I am developing sample apps and would like to know process.env variables,
I know console.log(process.env) will return its variables.
But can I see them after run its server ?
npm start
I couldn't input anything in console.
As I am new to node.js, will you please let me know.
by switing NODE_ENV, it seems that development,staging,production is switched.
So that I would like to comfirm them.
Thanks
If you start your server in docker and don't pass custom variables to process.env in your app, you can see your env by docker command:
docker exec your_container env
Yet another way - create a specific route in your application that will be return you all data from process.env.
Something like this:
GET yourserver/api/system/env
But this way is not secured and you should think about protection of your system route.
UPD
Also you can call console.log(process.env) after server has been started.
await app.listen(3000);
console.log(process.env);

Configure Enviroment Variables For Production Node.JS

I am trying to deploy my test Express.js app on Heroku using GitHub for resources and mlab for my database. In development th app doesn't have problems when I pass mLab connection string but in production... How must my production environment look?
Here is my config.js:
const env=require('dotenv').config();
module.exports = {
development: {
port: process.env.PORT|| 3000,
dbPath: process.env.DB_CONNECTION,
},
production: {
port: process.env.PORT|| 3000,
dbPath: process.env.DB_CONNECTION_MLAB,
}
};
Your .env file probably isn't (and shouldn't be) used in production. It should be ignored in your Git repository.
This means your production database configuration needs to come from somewhere else. If you're using the official mLab addon you can access your connection string via the MONGODB_URI environment variable, which the addon sets automatically.
If you're not using the official addon you should set the appropriate environment variable yourself, e.g. via
heroku config:set MONGODB_URI=...
In either case, make sure the name of the environment variable in your code matches what's set in the environment. Generally there is no need for separate development and production variables since they are set in different environments. I recommend using MONGODB_URI everywhere.

How to separate express server code from Express business logic code?

All the Node.js tutorials that I have followed have put everything in one file. It includes importing of libraries, routing, database connecting and starting of the server, by say, express.js:
var app = require('express');
app.get('/somePath', blah blah);
app.listen(...);
Now, I have 4 node servers behind an Nginx load balancer. It then becomes very difficult to have the source code updated on all the four servers.
Is there a way to keep the source code out of the server creation code in such a way that I can deploy the source code on the servers as one package? The server creation code should not know anything about routing or database connections. It should only be listening to changes in a folder and the moment a new module meta file appears, it starts hosting that web application.
Much like how we deploy a Java code packaged as war by Maven and deployed to the webapp of Tomcat, because Tomcat instantiation is not part of the source code. In node.js it seems server is also part of the source code.
For now, the packaging is not my concern. My concern is how to separate the logic and how do I point all my servers to one source code base?
Node.js or JavaScript for that matter doesn't have a concept like WAR. But what it does have is something similar. To achieve something WAR like, you would essentially bundle the code into one source file using something like webpack. However, this will probably not work with Node.js modules like http (Express uses `http since it likely calls or relies on native V8/C++ functions/libraries.
You could also use Docker and think of the Docker containers as WARs.
Here is what I figured out as a work around:
Keep the servers under a folder say, "server_clusters" and put different node servers there, namely: node1.js, node2.js, node3.js, node4.js, etc (I know, in the real world, the clusters would be different VMs or CPUs altogether but for now, I simply want to separate server creation logic from source code). These files would have this code snippet:
var constants = require('./prop');
var appBasePath = constants.APP_BASE_DIR;
var appFilePath = appBasePath + "/main";
var app = require(appFilePath);
//each server would have just different port number while everything else would remain constant
app.listen(8080, function (req, res) {
console.log("server started up");
});
Create a properties file that would have the path to the source code and export the object. That simple. This is what is used on line#1 in the above code
Create the source directory project wherever you want on the machine and just update its home directory in the constant file above. The source code directory can export one landing file that will provide the express app to the servers to start:
var express = require('express');
var app = express();
module.exports = app;
With this, there are multiple servers that are pointing to the same source code.
Hope this helps to those who are facing the same problem.
Other approaches are welcome.

Why does pushing my locally created MEAN-Application to OpenShift not work?

I'm trying to push my MEAN-Application, which I created locally using express, to OpenShift. For that, I create a new application from the dashboard and add NodeJS as a cartridge. When I then add my Git-Repository-URL (Hosted on BitBucket) and create the application, I get the following error:
When I create a new application without entering the repository URL and then pull from Openshift, copy in my Project and Push again, I get a similar error:
It seems to be some problem with port 8080 being unavailable but I cant resolve this myself as I'm new to this and couldn't find a solution on the web, so any help & advice is appreciated.
EDIT: when I say MEAN I actually mean EAN; I don't use MongoDB at the moment.
EDIT 2: after several hours I decided to try Heroku. It also didn't work on the first try but the Log contained far more useful information so I got everything up and running in about an hour (compared to like 4 hours of trying with OpenShift). After that I tried to push the exact same Project I pushed to Heroku to Openshift and got the following, new error:
Again, if somebody happens to know a quick fix for this please tell me as I would still like to use OpenShift.
Your NodeJS code should look something like this:
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
http.createServer().listen(port);
That will use the value of OPENSHIFT_NODEJS_PORT if it is available, and still use 8080 when you run the application outside of OpenShift. Or you could even set the environment variable OPENSHIFT_NODEJS_PORT=8080 on your local machine to more closely simulate the OpenShift environment.
Note that you should also check the environment variables to get the correct server IP address. See this documentation for more information.
What worked for me was the following:
Create App on OpenSHift, leave Repo Url empty for now.
Use git remote add openshift -f <openshift-git-repo-url
(ssh://...something)> to add the Openshift-Repo as a remote Repo to your Project.
Use git merge openshift/master -s recursive -X ours to merge the Openshift-Repo into your local Repo and keep your files if conflicts appear.
(And this is the important step) Your main File (bin/www for me) has to look something like this (I tried everything to format this but it just didn't format properly):
var app = require('../app');
var debug = require('debug')('CTW:server');
var http = require('http');
/**
Get port from environment and store in Express.
*/
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 3002);
app.set('ip', process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1");
/**
Create HTTP server.
*/
var server = http.createServer(app);
/**
Listen on provided port, on all network interfaces.
*/
server.listen(app.get('port') ,app.get('ip'));
git push openshift HEAD to push it to your Application Repo
As it turns out, I had to set the IP.
All credit goes to this and this questions answers.

Building applications for different environments with nodejs

Historically on most large projects I have worked on we have a build script of some sort which is run by a developer to setup their environment, such as setting up iis, database migrations, templating configuration files etc.
As each environment is different, I would generally have a set of configuration files for each environment, such as dev.config, qa.config or release-candidate.config, then when the build process runs it would use the <environment>.config file to find out what its settings should be. This way my dev environment can build fine and the build server can do its stuff fine too in an automated fashion.
Anyway in .net we have configuration files such as web.config which can be templated, is there any notion of this within the nodejs world? as I want to have a file which contains all the configuration values required for the application to run without putting them in the application code.
You can do that very simple, actually. Just place all your configuration in .js file, like
{
mongodb: {
connection: 'http://mongodb.com/mydb:12323/user/password',
options: {
keepConnection: true
}
},
app: {
deploymentKey: '1234'
},
// etc
}
So, you will have 2-3 files, depending on the number of environments you have.
/config/development.js
/config/production.js
/config/test.js
/config/staging.js
The environment type is typically exposed by NODE_ENV variable. Then you have really simple module, to load the configuration:
var util = require('util');
var env = process.env.NODE_ENV || 'development';
var config = util.format('/%s.config.js', env);
module.exports = require(__dirname + config);
Checkout some real code here;
This is why I created the properties module.
Check the environment example.

Resources