after around 12 hours of continuously trying a lot of things including asking Copilot I finally quit and made up mind to ask this.
I am having problem while running nodejs app.js on my server.
My server config are as follows:
- Server type: VPS
- OS: Linux: Ubuntu 24.x
- WebHost Manager: Webuzo
- Application handler: Webuzo’s default, (although it has "passenger" too)
- SSL: present, active, forced for all domains
- App file: app.js
- Webserver: OpenLiteSpeed
- App port (as defined by handler and in code): 30000
Now, if I run nodemon app.js
from cli or run the start from app handler in the interface. The application runs fine when the port is set to 30000 with express and no https configured.
Application is visible on:
- example.com – LiteSpeed redirects it to https://example.com (I believe that’s reverse proxy working on its own) as the https is forced on all domains. [Note: this is without implementing
https.createServer
or even importing it in myapp.js
file] - example.com:30000 – this is accessible on http:// which is what I wanted to be on https:// even if someone wants to access http:// on port 30000.
In the debugging/workaround things which I did to achieve, I added the https.createServer
after importing https and defining the cert
and key
files in options
.
Now what happened:
- example.com:30000 goes to https://example.com:30000 without hassle. Application is accessible/visible there.
- But now my default domain is broken i.e. http://example.com and https://example.com both are inaccessible (keeps on loading). [seems litespeed reverse proxy messed up]
My code:
import https from "https";
import http from "http";
import fs from "fs";
import express from "express";
import path from "path";
import { dirname } from "path";
import url from "url";
import {fileURLToPath} from "url";
import bodyParser from "body-parser";
import morgan from "morgan";
import "dotenv/config";
const app = express();
const httpApp = express();
const __dirname = dirname(fileURLToPath(import.meta.url));
var visitor = 1;
const port = 30000;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public'));
// app.use((req, res, next) => { if (!req.headers.host.startsWith('www.')) { return res.redirect(301, 'https://www.' + req.headers.host + req.url); } next(); });
const options = {
key: fs.readFileSync(path.resolve("example.com.key")),
cert: fs.readFileSync("example.com.crt"),
ca: fs.readFileSync(path.resolve("example.com-ca.crt"))
};
const httpsOptions = {
key: fs.readFileSync("example.com.key"),
cert: fs.readFileSync("example.com.crt")
};
httpApp.set('port',30001);
httpApp.get("*", function (req, res, next) {
res.redirect("https://" + req.headers.host + "/" + req.path);
});
function logger(req, res, next){
console.log("Request method: ", req.method);
console.log("Request URL:", req.url);
next();
}
app.use(morgan("tiny"));
//request method
app.use(logger);
app.post("/submit", (req, res) => {
console.log(req.body);
console.log(req.body.name);
var name = req.body.name;
var email = req.body.email;
res.send(`<h1>Hey ${name} with email id ${email}, we got your message, unfortunately we are unable to serve at this moment. </h2>`)
});
app.get('/', (req, res) => {
console.log(visitor);
res.sendFile(__dirname + "/public/index.html");
});
app.get('/test', (meow, bhow) => {
bhow.send("Testing works on Http2?");
// bhow.sendStatus(200);
});
app.use((req, res, next) => {
// res.status(404).render('status');
res.status(404).send(`<h1><center> The location <a href="https://${req.hostname}${req.originalUrl}">${req.hostname}${req.originalUrl}</a> is not available at this moment. <br><br> That's a 404 Not Found Error</h1></center>
<center>
<h2> Let's go back to home @ <a href="https://example.com">${req.hostname}</a></h2></center>`);
});
const servinginSSL = https.createServer(options, app);
servinginSSL.listen(30000, ()=>{
console.log("Running at port 30000");
});
// http.createServer((req, res)=>{
// res.writeHead(301, {"Location": `https://${req.headers.host}${req.url}`});
// res.end();
// }).listen(30000, () => {
// console.log("Http server ran and redirecting to HTTPS")
// });
// app.set('port', 30000);
// app.enable('trust proxy');
// http.createServer(httpApp).listen(httpApp.get('port'), function() {
// console.log('Express HTTP server listening on port ' + httpApp.get('port'));
// });
// https.createServer(httpsOptions, app).listen(30000, function() {
// console.log('Express HTTPS server listening on port ' + "30000");
// });
// app.listen(port, () => {
// console.log(`Running at ${port}`);
// });
I’ve tried a couple of solutions with changing proxy, rewrite rules of litespeed but nothing worked.
while not implementing https.createServer
and just going with app.listen(30000, ....)
seems to work fine when example.com
is accessed which automatically goes to https://example.com
.
I am just worried that port 30000 is also accessible without http which will make my app directly vulnerable anyway.
The stackoverflow answer which I tried: How can I adjust my NodeJs server code to responf to HTTPS requests?
Please help. I am a
2
Answers
😭 I found a way and it's working as intended. I am still not sure if it's right method (since I am new to vhost customization and all) but here you go:
I just edited the vhost files for my example.com for port 80 (
vhost.conf
) in litespeed folder.What I changed in the file was a simple line of code:
I just changed the
address 127.0.0.1:30000
to address https://127.0.0.1:30000Now,
example.com
is:https://example.com
without problems, working.https://example.com
without problems, working.https://example.com
ishttp://example.com:30000
ishttps://example.com:30000
isthis was done with nodejs using:
and in options:
ca file(s) might not be available under your control panel's ssl folder. Mine works even when I omit the ca key-value pair.
P.S. Last night copilot broke my brain after serving me an answer where the code asked http and https to listen to port 30000, and then copilot itself said one port cannot be assigned to two different things. 😭 I quit copilot then and there.
Reverse Proxy Method
I assume you are using the rewrite method to implement the reverse proxy with that "30000" External Applications.
If you simply want to force all traffic to HTTPS, then you can use rewrite cond, e.g.
RewriteCond %{HTTPS} off
to force it.If you can make your nodejs app support both HTTP and HTTPS, then you can create additional External Applications for it.
Rewrite Rule example will become like this,
App context method
Set up an App Server Context by following the OpenLiteSpeed NodeJS Context Guide, and let OLS handle the HTTP and HTTPS for you. In this case, OLS proxy traffic to Node.JS directly, and you don’t need to worry about Rewrite, HTTP, and HTTPS configuration issues.