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 | }
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}!`);
});
.env
PORT=443
The output of pm2 status
at the moment:
Any help would be appreciated!
Top comments (14)
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 π
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.
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 π
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!
Excellent! Out of interest did you use Nginx in the end or Apache?
Glad it's working for you now.
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!
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.
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.
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.
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!
Weβve seen something like this when pm2 is running as a service and then we launch from the command line.
Hello Bob and thanks for your input.
Can you clarify further? How can I run pm2 from the command line?
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.
Hello,
I have the same issue here, I notice that you already solve the issue.
could you please provide me with any hint to solve the problem.
thank you.
Hello Ahmad, I don't remember all the details now but this documentation page put me on the right track. I used an Apache virtual host file to redirect traffic from port 443 to port 4000.
I hope it helps.