DEV Community

loading...
Cover image for PM2 listening on port 443 shows EADDRINUSE: address already in use :::443

PM2 listening on port 443 shows EADDRINUSE: address already in use :::443

dmahely profile image Doaa Mahely ・2 min read

I have a Node/Express app running on an AWS Lightsail instance with PM2 as a process manager. The app is currently running on port 4000. The IP address for the instance is attached to a subdomain that has a valid SSL certificate and automatically redirects from HTTP to HTTPS. Visiting https://example.com at the moment shows the 'Congratulations! You are now running Bitnami Node.js 12.18.3 in the Cloud.' page.

Currently, all the Express endpoints are only accessible through http://example.com:4000/endpoint, but I want the Express app to run on port 443 so that the endpoints are accessible immediately on https://example.com/endpoint.

I read that PM2 is able to listen on ports 80 and 443 and tried the method mentioned in the documentation, but whenever I change the port number in the .env file to 443 and reload the app using pm2 reload app, I get the following error:

0|app    | Error: listen EADDRINUSE: address already in use :::443
0|app    |     at Server.setupListenHandle [as _listen2] (net.js:1313:16)
0|app    |     at listenInCluster (net.js:1361:12)
0|app    |     at Server.listen (net.js:1447:7)
0|app    |     at Function.listen (/opt/bitnami/apache/htdocs/node_modules/express/lib/application.js:618:24)
0|app    |     at Object.<anonymous> (/opt/bitnami/apache/htdocs/app.js:44:5)
0|app    |     at Module._compile (internal/modules/cjs/loader.js:1137:30)
0|app    |     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
0|app    |     at Module.load (internal/modules/cjs/loader.js:985:32)
0|app    |     at Function.Module._load (internal/modules/cjs/loader.js:878:14)
0|app    |     at Object.<anonymous> (/opt/bitnami/node/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23) {
0|app    |   code: 'EADDRINUSE',
0|app    |   errno: 'EADDRINUSE',
0|app    |   syscall: 'listen',
0|app    |   address: '::',
0|app    |   port: 443
0|app    | }
Enter fullscreen mode Exit fullscreen mode

App.js

const express = require('express');
const dotenv = require('dotenv');

const app = express();
app.use(express.json()); // for parsing POST bodies
dotenv.config();

app.get("/hello", (req, res) => res.send("Hello World!"));

app.listen(process.env.PORT, () => {
    console.log(`🥁 App listening on port ${process.env.PORT}!`);
});

Enter fullscreen mode Exit fullscreen mode

.env

PORT=443
Enter fullscreen mode Exit fullscreen mode

The output of pm2 status at the moment:
aSXDK

Any help would be appreciated!

Discussion (12)

pic
Editor guide
Collapse
codebubb profile image
James Bubb

As the error suggests there is another application that is already bound to port 443. If you're using the Bitnami Node stack I would assume that application would be Apache.

Normally, you would run your application on a local port (e.g. 4000) and then have a reverse proxy (I'm only familiar with Nginx I'm afraid) to make the link between the public web port (e.g. 80 or 443) and your local app, rather than binding your app with pm2 to port 443.

I took a look at some of the documentation for the Bitnami Node.js stack and that is indeed what they suggest doing. docs.bitnami.com/aws/infrastructur...

If you have a look at step 3, they show you how to setup a virtual host for Apache with the reverse proxy to your local Node.js app. It might be worth taking a look at this and revisiting your app setup.

Hope that helps 😀

Collapse
dmahely profile image
Doaa Mahely Author

Hi James, thanks a lot for your input.
Yes, although I wanted to use authbind with pm2 but it seems impossible with no documentation and open issues with no responses.
I've been trying to do something like this where I installed nginx and set up the configuration, but got stuck at the last step where I need to reload Nginx but when I need to run or reload it for the config to be updated.

$ sudo nginx -s reload
nginx: [error] invalid PID number "" in "/run/nginx.pid"
Enter fullscreen mode Exit fullscreen mode

Some of the commands are different because of the different Ubuntu installations. I will check out the link you mentioned and get back to you 🙏

Collapse
dmahely profile image
Doaa Mahely Author

Update: Site is up and running!

I wouldn't have found that page of documentation with that title. Now I learned yet another method of solving this particular problem 😄
Thanks a lot for taking the time to help James!

Thread Thread
codebubb profile image
James Bubb

Excellent! Out of interest did you use Nginx in the end or Apache?

Glad it's working for you now.

Thread Thread
dmahely profile image
Doaa Mahely Author

I ended up using Apache and configuring virtual hosts to redirect the traffic, because I couldn't find any complete Nginx tutorials! The Apache method is dead simple and I'm surprised I didn't come across it in my research.

Cheers!

Collapse
motss profile image
Rong Sen Ng

I usually don't listen to port 80 or 443. I'll use reverse proxy instead to do the mapping. For HTTPS, I guess you can redirect all requests that come from the Internet to use HTTPS so that everyone can only access your API securely. Also you might want your other API to access the HTTP version of your API. That's how it's usually done.

Collapse
dmahely profile image
Doaa Mahely Author

Hello Rong and thanks for your input.

So you mean something like this:
example.com sends a GET request to api.example.com which redirects to api.example.com:3000?

I need the frontend calls to go to port 443 on the Express server because I had an SSL error when trying to do requests directly to api.example.com:3000, I assumed because I'm not allowed to make an insecure request from a secure website.

Collapse
motss profile image
Rong Sen Ng • Edited

Your redirect is not what the redirect I was talking about. What I meant was to redirect all unsecured HTTP requests to secured HTTPS requests. If you are able to do that, your express app won't need to listen to port 80 or 443 whatsoever.

Your express app should work with IP addresses and ports only. The picture would look like this:

user visits (https)api.example.com --- your load balancer or any proxy in between that should accepts only listen to port 80 and 443 will route to your express app --- reroute traffic to express app at :3000 --- your express app at port 3000 will process the request

For redirect, it looks like this:

User visit (http)example.com --- your proxy asks browser to go to (https)example.com --- browser visits (https)example.com again --- proxy allows and reroute to your express app.

So it's more of your proxy between the internet and your express app. For that people might use nginx or equivalent to do that. You might have something simpler depends on your cloud service provider.

Thread Thread
dmahely profile image
Doaa Mahely Author

Ah yes, I got your point. I had HTTP to HTTPS redirection set up already but needed the extra step of redirecting from 443 to 3000 where the endpoints lived.

I got it working eventually, thanks for your time!

Collapse
bob_benedict profile image
Bob Benedict

We’ve seen something like this when pm2 is running as a service and then we launch from the command line.

Collapse
dmahely profile image
Doaa Mahely Author

Hello Bob and thanks for your input.
Can you clarify further? How can I run pm2 from the command line?

Collapse
bob_benedict profile image
Bob Benedict • Edited

This is how we start it in the root folder of our repo: pm2 start node src/ -i max. We don't normally run it this way but some times it is handy when making configuration changes.