19
votes

I am running a Express.js app on Amazon Elastic Beanstalk and my environment was successfully created, but when I go to my environment via the URL Amazon has created, I receive a 502 Bad Gateway nginx/1.6.2 error. While I have read other resources on StackOverflow, which suggest I rename my main file from server.js to main.js and set the port in a bin/www folder, I feel like this isn't the solution for my app. I ran node server.js, which is the command I believe Elastic Beanstalk runs and it doesn't work, (error message):

node server.js
events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: failed to connect to [undefined:27017]

because I have ENV variables set up in a .env file, so the only way I can run my server is with foreman. This has made me think that the 502 error is the result of Elastic Beanstalk not being able to comprehend the variable and thus causing the server to fail. Can anyone confirm that I am on the right path or is this issue really because my main file is named server.js and not in the bin/www folder?

Here is my code from my server.js file:

//Load express
var express = require('express');
var app = express();
var router = express.Router(); // get an instance of the router
var bodyParser = require('body-parser'); // configure app to use bodyParser()
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var aws = require('aws-sdk');

app.use(bodyParser.urlencoded({ extended: true})); // get data from a POST method
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use(cookieParser());


var port = process.env.PORT || 8080; // set the port

var DB_CONFIG = process.env.DB_CONFIGURATION;
var AWS_ACCESS_KEY = process.env.AWS_ACCESS_KEY;
var AWS_SECRET_KEY = process.env.AWS_SECRET_KEY;
var S3_BUCKET = process.env.S3_BUCKET;

var blogDB = require('./config/blogDB.js');
mongoose.connect(blogDB.url);




require('./config/passport.js')(passport);


app.set('view engine', 'ejs'); // set ejs as the view engine

app.use(express.static(__dirname + '/public')); // set the public directory

app.use(session({ secret: 'thisisatest' }));
app.use(passport.initialize());
app.use(passport.session());

app.use(flash());


var routes = require('./app/routes');

app.use(routes); // use routes.js


app.listen(port);
console.log('magic is happening on port' + port);

and my package file:

{
  "name": "test",
  "main": "server.js",
  "dependencies": {
    "body-parser": "1.6.5",
    "ejs": "^1.0.0",
    "express": "^4.6.1",
    "express-paginate": "0.0.2",
    "mongoose": "~3.6.15",
    "mongoose-paginate": "^3.1.0",
    "serve-favicon": "*",
    "passport" : "~0.1.17",         
    "passport-local" : "~0.1.6",
    "connect-flash" : "~0.1.1",     
    "bcrypt-nodejs" : "latest",
    "morgan": "~1.0.0",
    "cookie-parser": "~1.0.0",
    "method-override": "~1.0.0",
    "express-session": "~1.0.0",
    "aws-sdk": "*" 
  }
}
12
You are running the nodejs app behind an nginx proxy ? Have you setup the correct reverse proxy configuration ?Noman Ur Rehman
@cphill: Looking at your logs, it seems that deployed application is not getting right mongoDB path Error: failed to connect to [undefined:27017]. Did you try setting up NODE_ENV to right value from EBS console?Raeesaa

12 Answers

16
votes

I had the same problem tonight. It turned out that the node app had not been started even though the portal claims that it will run npm start by default.

Here is what I did to fix it:

  1. Create a directory named .ebextensions in the root of my project
  2. Inside .ebextensions create a file named nodecommand.config
  3. Inside the nodecommand.config add the following yaml:
option_settings:
  - namespace: aws:elasticbeanstalk:container:nodejs
    option_name: NodeCommand
    value: "npm start"

The full instructions are available here: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs_express.html

8
votes

From the EB App Dashboard, go to Configuration -> Software Configuration -> add value "npm start", or "node 'yourmainfile'" to the Node Command.

Even though AWS shows "Command to start the Node.js application. If an empty string is specified, app.js is used, then server.js, then "npm start" in that order", it looks like it doesn't run unless you specify.

5
votes
  1. Add "scripts": { "start": "node app.js" } to your package.json. If your main js file is not app.js, don't forget to rename it! :)

  2. In Beanstalk console: Configuration->Software add new env var: port: 8081 (PORT: 8081) enter image description here

Important: even if you add env var as port you still have to use PORT (uppercase). That is what solved my problem. I tried to use process.env.port, but it did not work. Use process.env.PORT instead.

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log("Server is listening on: ", port);
});
4
votes

In my case the issue was my port, my express server was listening on port 80. I just needed to change it to 8081 because i think the EB reverse proxy (nginx/apache) tries to redirect traffic to 8081 by default.

I figured it out by checking the AWS EB access logs.

2
votes

For my case I'm sharing what worked for me for error 502 Bad Gateway Nginx.

AWS Elastic Beanstalk is using Nginx as Proxy Server for Load Balancing, even if you just started.

I went from the AWS EB Console Management to look for Error logs from Nginx. Always check log because your error might be different from others.

Now let's say your IP is AAA.BBB.CCC.DDD. I found out in the error, Nginx received requests from AAA.BBB.CCC.DDD and forward it to AAA.BBB.CCC.DDD:8081. And since I started Node to port 3003 in my code, so I had to change it for Production or whatever you call your AWS EB Server environment.

You can do it with ENV to maintain flexibility if you want (ENV can be added directly to EB Console). Once you put PORT to 8081, make sure you commit because Elastic Beanstalk follow GIT rules to know which file to take, if you don't commit, it will not deploy the change.

Once you're done, use command eb deploy and watch it works now.

2
votes

For me the error was because I didn't set "npm start" in the software configuration section even though I did before creating the app. Seems there was some bug and I had to set it again so kindly check whether its set or not!

1
votes

I was also facing this but it was because of absense of one of the npm module. You can see the missing npm model name in the log section of elastic beanstalk dashboard. It was working fine in my local machine just because that particular npm module was globally installed in my system.

1
votes

Evening all

In my experience, you typically will receive this error when you are not running Express on the correct port.

Nginx try's to route traffic from port 8081 to the server, which could be load balanced.

As such, you should explicitly ensure you use port 8081 as your Express listening port (e.g process.env.PORT=8081)

Thanks

Keaton

1
votes

I forget to run npm install after cloning, sudo npm install worked for me.

1
votes

Note that NodeStart is now considered "legacy":

You can add a Procfile to your source bundle to specify the command that starts your application, as the following example shows. This feature replaces the legacy NodeCommand option in the aws:elasticbeanstalk:container:nodejs namespace.

The same document (source below) states:

When you don't provide a Procfile, Elastic Beanstalk runs npm start if you provide a package.json file. If you don't provide that either, Elastic Beanstalk looks for the file app.js or server.js, in this order, and runs it.

Source: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_nodejs.container.html

1
votes

Make sure that the scripts section in your package.json file looks like this:

"scripts": {
     //whatever other scripts

     "start": "node app.js",

     //whatever other scripts
},
0
votes

In my case it was process.env.port in index.js. The port was in a small case. I modified it to process.env.PORT