Do I change app.listen('port number') when I finally publish my website to a hostserver? - node.js

This is my first time publishing a website so excuse me if my question sounds dumb or easy. So I finally finished the frontend and backend of my website and I'm going to publish it to a hostname from namecheap.com. I'm using express and an abstract example of how my backend looks would be like this:
const express = require("express");
const app = express();
const path = require('path');
app.use(express.static("./public"));
app.listen(5000, () => {
"server is listening!!"
})
I realize that using app.listen(5000, () => {}) is due to listening to a port in the local host. So how do I change it to finally publish it and for my hostserver to recognize it.

use nginx or apache upstream ,
apache and nginx as ssl termination , more secure and if you add caching you could handle more request per second
nginx config :
server {
#listen 80 ;
#listen [::]:80 ;
listen 443 ssl ;
server_name namecheap.com;
ssl_certificate /etc/nginx/ssl/domain-crt.txt;
ssl_certificate_key /etc/nginx/ssl/domain-key.txt;
ssl_session_cache shared:SSL:1m; # holds approx 4000 sessions
ssl_session_timeout 1h; # 1 hour during which sessions can be re-used.
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_buffer_size 4k;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://localhost:5000;
proxy_buffering on;
}
}

If you are gonna host the website you might wanna add a port variable and assign the following value to it.
const PORT = process.env.PORT || 5000;
When you are on localhost testing the website the port variable will use the
5000
value otherwise when hosting the hosting service provides its own port to run the server which is the
process.env.PORT
make sure "PORT" is all caps. Then for running the server-
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server Started at Port ${PORT}`)
});
That should do it!

Related

What's the correct way to get rid of /public from a domain using node.js and nginx?

I've been structuring my website as follows:
someSite
app.js
public
index.html
css
assets
Project1
Project2
...
I'd like for the path to /public/Project1/index.html to be accessible by going to someSite.com/Project1, and similarly for subfolders. I've found this can be accomplished like this:
var express = require('express');
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.use('/public',express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
app.get('/Project1', (req, res) => {
res.sendFile(__dirname + '/public/Project1/index.html');
});
But I don't know if this is standard, or inefficient. It's also breaking all of my relative calls, such as <img src="../assets/someImage.svg">, which no longer point to the correct place. It can be fixed by using absolute urls everywhere, but that feels wrong.
I'm using nginx as a reverse proxy server, which I think is the right place to make this change. My configuration is as follows:
server {
listen 80;
server_name someSite.com www.someSite.com;
rewrite ^(.*) https://$host$1 permanent;
}
server {
listen 443 ssl;
root /var/www/someSite/public;
server_name someSite.com;
ssl_certificate /path/to/credentials.crt;
ssl_certificate_key /path/to/credentials.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:3000/;
}
}
I still haven't figured out exactly what's wrong with my nginx configuration, but the hosting from node issue was just a matter of changing
app.use('/public',express.static(path.join(__dirname, 'public')));
to
app.use('/',express.static(path.join(__dirname, 'public')));
and removing subsequent app.get calls.

How to serve static files (CSS, ...) with multiples Express app + NGINX as reverse proxy server

Context
I'm runnig multiples nodesJS/Express app on the same server with the same IP adress.
I use Nginx to reverse proxy those apps and redirect it to subfolder adress (and not subdomain, i don't want to).
ex : http://123.0.0.1:8000 => http://monsite.com/Site1
Problem
My assets files (css, images, ...) do not load, I have a 404 error on those static files when the page loads. It happens only when I access the site via the proxy redirect http://monsite.com/Site1 and not when I use the IP adress : http://123.0.0.1:8000
I don't have this problem if a use the reverse proxy location from the root in the nginx conf :
location / {
but I want to access the site from a subfolder adress
My integration
Tree files:
var/www/html
|Site1/
| |server.js
| |Views/
| | |index.pug
| |Public/
| | |Css/
| | | |Style.css
|Site2/
|....
nodejs server code
const PORT = 8000;
const HOSTNAME = 'www.monsite.com';
// Dependencies.
const express = require('express');
const http = require('http');
// Initialization.
var app = express();
var server = http.Server(app);
app.set('port', PORT);
app.set('view engine', 'pug');
app.set('views','Views');
app.use(express.static('Public'));
app.use('/', (request, response) => {
response.render('index');
});
server.listen(PORT, HOSTNAME, function() {
console.log(`STARTING SERVER ON PORT ${PORT}`);
});
index pug code
doctype html
html
head
title Site 1
link(rel="stylesheet" href="/Css/style.css")
body
p Hello
nginx conf
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html index.htm index.nginx-debian.html index.php;
server_name www.monsite.com;
location / {
#Reserved for another site
}
location /Site1/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
proxy_pass http://123.0.0.1:8000/;
}
}
PS : I tried almost all the solutions and code I found searching for this problem and nothing worked, that's why I'm asking directly here. Thank you.
I think the issue is with the url in the link tag to load the css, the url is invalid because the url is actually /Site1/Css/style.css.

Node: PORT 443 requires elevated privileges error

I'm using PM2 to start the application and I pass PORT=443 as a parameter while starting the app. However, it returns with an error saying "PORT 443 requires elevated privileges". Though I have generated the certificate and key using openssl and referenced in the code. Appreciate your support
#!/usr/bin/env node
var app = require('../app');
var debug = require('debug')('ls-templates-server:server');
var https = require('https');
var fs = require('fs');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var options = {
key: fs.readFileSync('/home/admin/cert/server.key'),
cert: fs.readFileSync('/home/admin/cert/server.cert')
};
var httpsServer = https.createServer(options, app);
/* for https (production stage) */
httpsServer.listen(port, "0.0.0.0");
httpsServer.on('error', onError);
httpsServer.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = httpsServer.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
Option 1 .
Run PM2 as sudo
If it doesn't work, achieve it using authbind
sudo apt-get install authbind
sudo touch /etc/authbind/byport/443
sudo chown %user% /etc/authbind/byport/443
sudo chmod 755 /etc/authbind/byport/443
Edit ~/.bashrc file and add
+alias pm2='authbind --deep pm2'
at the end of the file, and run
source ~/.bashrc
Finally ensure that pm2 is updated with authbind:
authbind --deep pm2 update
Option 2
Use a different PORT and use Nginx to reverse proxy your application
Eg : change your PORT to 3000
In Nginx , create a server block which forwards the request to your application.
Server Block Eg :
server {
#listen [::]:80;
server_name your-domain.com
#root /var/www/example.com;
#index index.html;
client_max_body_size 20M;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_connect_timeout 500000;
proxy_send_timeout 500000;
proxy_read_timeout 500000;
send_timeout 500000;
}
listen 443 ssl;
ssl_certificate /home/admin/cert/server.cert;
ssl_certificate_key /home/admin/cert/server.key;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
}
It's best to use Nginx / Authbind method, It's good to run as little as possible as a privileged user, as you want to restrict the potential damage in case someone exploits your program. You don't want to run your Node code as root unless you absolutely have to.
refer
https://pm2.keymetrics.io/docs/usage/specifics/#listening-on-port-80-w-o-root
https://www.digitalocean.com/community/tutorials/how-to-use-pm2-to-setup-a-node-js-production-environment-on-an-ubuntu-vps

Configure Nginx for file upload using connect-busboy

I have an API in NodeJS where I can upload a file, and I receive it on the server side using the connect-busboy package.
So, for example, here is a part of the code that handles the request:
var app = require('express')();
var busboy = require('connect-busboy');
app.use(busboy({
highWaterMark: 2 * 1024 * 1024,
limits: {
fileSize: 1024 * 1024 * 1024 // 1 GB
},
immediate: true
}));
var busboyHandler = function (req, res) {
if (req.busboy) {
req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
console.log('received file ', req.path, fieldname, file, filename, encoding, mimetype);
});
req.busboy.on('field', function(key, value, keyTruncated, valueTruncated) {
console.log('field..', key, value, keyTruncated, valueTruncated);
});
req.busboy.on('finish', function() {
console.log('busboy finished');
});
}
};
app.post('api/documents/files', busboyHandler);
This works well when I start the API with npm start and upload the file to this API directly, however, when I configure an Nginx Docker, it works for really small files, but for most files, they don't get uploaded successfully.
Here is an excerpt from my nginx.conf file:
user nobody nogroup;
worker_processes auto; # auto-detect number of logical CPU cores
events {
worker_connections 512; # set the max number of simultaneous connections (per worker process)
}
http {
include mime.types;
client_max_body_size 100M;
client_body_buffer_size 256k;
upstream api_doc {
server 192.168.2.16:4956;
}
server {
listen *:4000; # Listen for incoming connections from any interface on port 80
server_name localhost; # Don't worry if "Host" HTTP Header is empty or not set
root /usr/share/nginx/html; # serve static files from here
client_max_body_size 100M;
client_body_buffer_size 256k;
location /api/documents {
proxy_pass http://api_doc;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
I see the received file log, but when it's under Nginx, there is never a busboy finished log, unlike when calling the API directly without Nginx.
I tried changing these Nginx configs but it did not work: client_max_body_size, client_body_buffer_size. It looks to me like the API receives only a chunk of the file for larger files, instead of the whole file, or all chunks, as it should.
Any help would be appreciated.
Thanks,
Simon
It turned out that the problem was elsewhere, I was starting to read the incoming stream before the file was fully uploaded, so it led to breaking the incoming stream for some reasons.

SSL certificate on NginX

I have a DO droplet with nginX running 8 node apps as proxy servers.
For one of those i have a specific domain (e.g. 192.22.XX.20: 8888 -> mydomain.com) and I need HTTPS to get audio from users mic.
I have a PositiveSSL certificate defined on NginX but when i try to use it on that node app, nothing works. What Am I doing wrong?
nginx.default.conf
...
ssl on;
ssl_certificate /etc/nginx/ssl/.../ssl-bundle.crt;
ssl_certificate_key /etc/nginx/ssl/.../private.key;
ssl_prefer_server_ciphers on;
...
#proxy to a node app running on 8005 port
location /interpretame/ {
#return 301 $scheme://localhost:8005$request_uri;
proxy_pass http://localhost:8005/;
}
node app.js
```
...
var https_options = {
ca: fs.readFileSync("./cert/example_ca.crt"),
key: fs.readFileSync("./cert/example.key"),
cert: fs.readFileSync("./cert/example.crt")
};
...
https.createServer(https_options, app).listen(port, function(err) {
if (err) {
console.log(err);
return;
}
console.log('Listening over HTTPS at ' + port);
});
```
How do you define the 'nothing works'? :)
The application does not boot at all? If yes, it is quite possible that this happens if you start the application with node app.js. You have to start the application with sudo node app.js and by the way this is very bad practice.

Resources