Deploy node js express application - cent os - node.js

I am trying to deploy a node js application on GoDaddy VPS hosting.
I have uploaded all the files to the server and started the server using pm2
following This Tutorial
My server is running on port 3021 which I want to run on port 80
for a particular domain.
I have completed steps till pm2 in the tutorial but from Nginx part, I cannot understand what to do next.
I have installed Nginx then running this command sudo vi /etc/nginx/sites-available/default
and adding configurations and when I am saving it an error shows [ Error writing /etc/nginx/sites-available/default: No such file or directory ]
I am running apache in the server. Is it possible to do the same using apache??
Edit
Here is my nginx config::
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
}

So if you have pm2 running then you are half way through :) About nginx conf. This command: sudo vi /etc/nginx/sites-available/default probably does not work because the sites-available directory does not exist. Keep in mind that sites-available and sites-enabled are not required by nginx. It's just a good practice to have each server config in a separate file. But nginx will work without them too. If you are not planning to add any more servers, just use the /etc/nginx/nginx.conf file to configure your server. What you need to do is to create a new server block with desired configuration, e.x:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name yourapp.com www.yourapp.com;
root /var/www/html; # <- for you it can be any other dir
index index.html index.htm # <- or any other file which is your main file
# You want to proxy_pass the traffic on any route to your internal app
location ~ /(.*) { # ~ means that you are using regex
proxy_pass http://localhost:3021/$1$is_args$args; # <- proxy_pass to your internal app
proxy_redirect off;
proxy_read_timeout 60s;
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;
}
}
Just place the above config into /etc/nginx/nginx.conf inside http block.
Now check your nginx config:
nginx -t
If it's successful, your nginx config is done.
It's not over yet. One more thing to do- open port 80 in the firewall, like so:
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
You can check if it's open:
firewall-cmd --list-ports
Open your browser at http://yourapp.com/ and see if it works.
Remember to keep an eye on nginx and your app's logs:
tail -f /var/logs/nginx/access.log # or error.log to see nginx access/error log
pm2 logs # to see your app logs
Hope it helps. Do not hesitate to share more info if you encounter any more problems

Try to use /etc/nginx/conf.d/default.conf instead of /etc/nginx/sites-available/default to add your configuration. According to your config it should be the correct path to configure your server.
If you want to use /etc/nginx/sites-available/defaultyou should add include /etc/nginx/sites-available/*; to your nginx.conf.
http {
...
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-available/*;
}

Related

Is it dangerous opening port 3000 of the server?

I want to deploy my Angular + NodeJS application. My NodeJS application runs on http://localhost:3000 on the server. And my Angular application tries to send it's requests to the server with this prefix address: http://server.ip.address:3000. I opened the port 3000 of the server with the following commands to help my program works and it works fine by now.
irewall-cmd --zone=public --add-port=3000/tcp --permanent
firewall-cmd --reload
But I am not sure if I did a good job or not?
My Angular app runs on nginx and my NodeJS app runs on PM2. I also tried to setting a reverse proxy as you can see below inside etc/nginx/nginx.conf, but it didn't work and just opening port 3000 worked for me!
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /demo/stock-front9/dist/strategy;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
#proxy_pass http://localhost:3000;
#proxy_http_version 1.1;
# First attempt to serve request as file, then
# as directory, then redirect to index(angular) if no file found.
try_files $uri $uri/ /index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
What is the best way to deploy Angular + NodeJS application and how can I do it?
You can deploy the app by just assigning port to process.env.PORT, and put the whole angular build in a public/src folder and give the public folder path in node server file.
You can take reference here https://github.com/Ris-gupta/chat-application
There's no best way but there some best practices. Opening port directly on a server is not good solution. I would suggest you to use docker and publish your application inside container with NGINX. Also you can deploy your backend server in same way.

Should I open port 3000 of my server to serve NodeJS application?

I have an Angular + Node.JS app. When I was running the program locally I defined a baseurl = http://localhost:3000/ in my Angular app and used this prefix for accessing to my NodeJS backend in my program defined links, but now when I wanted to deploy my app on a remote server, I changed the baseurldefinition to the baseurl = http://111.222.333.444:3000/(111.222.333.444 is my server ip address for example), but it doesn't work!
How should I connect my Angular app to the NodeServer on a remote server?
EDIT: This is my /etc/nginx/nginx.conf file content:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /demo/stock-front9/dist/strategy;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
#proxy_pass http://localhost:3000;
#proxy_http_version 1.1;
# First attempt to serve request as file, then
# as directory, then redirect to index(angular) if no file found.
try_files $uri $uri/ /index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
I would not, I think is better to run the Node app with a tool like PM2 and then place a reverse proxy using Nginx in front of it, PM2 will act as orchestrator over your service while Nginx will provide access only through standard web ports (80, 443).
And in the case of Angular, when compiling, it should generate a static web app which you can serve using the same Nginx reverse proxy, doing it like so you'll save yourself the effort of configuring things like CORS, API routes and so forth, everything will go through Nginx.
Update on an example of Nginx config file
server {
listen 80;
server_name example.org;
location /api {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_http_version 1.1;
}
location / {
root /path/to/angular/compiled/app;
index index.html;
}
}
And then the angular app should point to the same host.
Good luck and cheers :)
You can still run your angular app locally. And for backend server, you can use proxy.
Please take a look at this.
https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md#using-corporate-proxy

Nginx on ec2 instance does not serve static files

What was working
I have MERN stack dashboard up and running on AWS EC2 instance.
Ec2 instance is at ec2...aws.com
React app is served on port 5004.
Node app is running on port 5003.
What was changed
The problem started when I set up the domain at GoDaddy to forward (with masking)
from somebusiness.com to ec2.....aws.com.
First, I set up NGINX reverse proxy to serve / as my react app (frontend) and /api as my node app (backend)
(you will find nginx code down below later)
http://somebusiness.com/ <- opens up React app and is working correctly
http://somebusiness.com/api/heartbeat <- not working as I expected (heartbeat is just endpoint to check if the app is alive) but for some reason, does not return application/JSON but rather a text/HTML webpage with the correct 'real URL' inside a frame of some kind:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <title>Somebusiness Dashboard</title>
  <meta name="description" content="">
  <meta name="keywords" content="">
</head>
<frameset rows="100%,*" border="0">
  <frame src="http://ec2-...aws.com/api/heartbeat" frameborder="0" />
</frameset>
</html>
The actual URL in the frame is the one that is working as expected:
http://ec2-...aws.com/api/heartbeat <- is working correctly
I think GoDaddy has something to do with this because on GoDaddy I can specify title, description, and keywords for this forwarding. So as backend, I'm forced to use http://ec2-...aws.com/api/ as my backend URL, which is OK for now (it is my secondary problem at the moment since it's just convenient to use the domain name for backend as well)
Main Problem
if i send a request to
http://ec2.....aws.com:5003/uploads/avatars/user1.jpg
the image is loaded OK.
So if i send a request to
http://ec2.....aws.com/api/uploads/avatars/user1.jpg
the image is NOT loaded.
So to recap: http://ec2-...aws.com/api/ is working OK for routes and requests, but not for serving static files. That leads me to believe my nginx setup is wrong, and I've spent countless hours trying all kinds of different setups. Here I present where i left it:
Source & code for help
Since I'm using Amazon Linux 2, I've used its tools to install nginx1 and set-up reverse proxy.
When i used NGINX on my other VPS, there was a bit different structure to it (sites-enabled & sites-available folders). But on this nginx there is only nginx.conf file where I did the setup. (I guess it doesn't make difference, just wanted to note that)
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name eyeratereviews.com;
root /home/ec2-user/somebusiness-web-backend;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
include /etc/nginx/mime.types;
location / {
proxy_pass http://127.0.0.1:5004;
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;
}
location /api {
root /home/ec2-user/somebusiness-web-backend/uploads/avatars;
default_type application/json;
proxy_pass http://127.0.0.1:5003;
# Following is necessary for Websocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
My node.js project folder structure is like this
...
controllers/
models/
static/
- pictures/
-- logo.png
uploads/
- avatars/
-- user1.jpg
-- user2.jpg
-- ...
Your existing code does not attempt to remove the /api from the front of the URI before passing it upstream. Add a trailing / to both the location and proxy_pass values. For example:
location /api/ {
proxy_pass http://127.0.0.1:5003/;
...
}
See this document for details.
Alternatively, use a rewrite...break to modify the URI instead.
For example:
location /api {
rewrite ^/api(.*)$ $1 break;
proxy_pass http://127.0.0.1:5003;
...
}
See this document for details.

EPIPE Error with ExpressJS, nginx proxy server

I am running multiple ExpressJS Node apps through an Nginx proxy server, and am getting an EPIPE Error thrown whenever my users try to download a file. This does not happen on my local setup (which is identical to the server's except for the proxy server), so I figure it has something to do with my Nginx configuration.
Here are my Nginx configs:
/etc/nginx/nginx.conf
user www www;
worker_processes 1;
error_log /home/alex/logs/error.log;
pid /var/run/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 4096; ## Default: 1024
}
http {
include mime.types;
index index.html index.htm index.php;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /home/alex/logs/access.log main;
sendfile on;
tcp_nopush on;
gzip on;
server_names_hash_bucket_size 128; # this seems to be required for some vhosts
include /etc/nginx/conf.d/*.conf;
}
/etc/nginx/conf.d/default.conf
server {
listen 80;
server_name example.com;
# log access and stuff
access_log /home/alex/logs/example-site.log main;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
# Proxy to the NodeJS server
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8999;
}
# redirect server error pages to their HTML
include /etc/nginx/errpages.conf;
}
The ExpressJS server is sending the download using the following code:
app.get('/citrite/p/:patch', function(req, res)
{
if(set.citFiles.indexOf(req.params.patch) == -1)
{
res.send(mbuild.get404());
}
else
{
track.incrViewcount(req.params.patch, 'citrite');
res.download(set.citDir + '/' + req.params.patch, files.doneSaving);
}
});
That code and everything else works fine on my local git repo, but when I push from there and pull on the server-side, the site kicks and screams - it times out on the user's end and gives me an EPIPE error in the console. I am running Node.js version 4.2.1 and ExpressJS version 4.13.3.
I figured out what the problem was: apparently, having sendfile set to on is what was causing the downloads to stall, and turning that off (specifically, removing the directive in the config) fixed the issue. Not exactly sure why this would interfere, but getting rid of the setting cleared things up.

How to set and configure node.js with express to nginx reverse proxy on centos 6.4 virtualbox client?

I am creating a development VM on my Windows 8.1 system using VirtualBox 4.3.4 and installed CentOS 6.4 as my VMServer. I installed NginX and Node.js with no problems. With little knowledge of administration I deleted the contents of /etc/sysconfig/iptables allowing all connections for development purpose only as of the moment (which will be changed later).
NginX is working fine, on my Windows host, and pointing the browser to http://192.168.1.20 shows that the "Welcome to nginx on EPEL!" page is working.
Verifying that my node.js app is working correctly, I created a node app on my VMServer by running
[~]# express node_nginx_practice
[~]# cd node_nginx_practice && npm install
[~]# node app
Then, on my Windows host, point the URL to http://192.168.1.20:3000, the "Express default" page is running with no problem.
The question is how could I set and configure node app to serve on nginx reverse-proxy?
example: http://192.168.1.20 //will point to Express default page
I tried setting my nginx config in /etc/nginx/nginx.conf by following some tutorials on the web with no luck url still points to the NginX "Welcome to nginx on EPEL!" page.
Here's my nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
#error_log /var/log/nginx/error.log notice;
#error_log /var/log/nginx/error.log info;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
# Load config files from the /etc/nginx/conf.d directory
# The default server is in conf.d/default.conf
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
}
}
I know I am missing something. Could someone point me to right direction?
EDIT ANSWER:
Here's what i did to solve the issue in step by step! (Thanks to "C Blanchard")
edit the default NginX config file:
[~]# vim /etc/nginx/conf.d/default.conf
and comment everything that is inside by prepending "#" to all of the lines.
restart NginX
[~]# /etc/init.d/nginx restart
Now the url points to the express page.
EDIT UPDATE: Better solution.
Open /etc/nginx/conf.d/default.conf find the location block and comment it by appending "#", and change specify the right location block pointing to node.js app. See code example below.
...
#access_log logs/host.access.log main;
# Comment this block
#location / {
# root /usr/share/nginx/html;
# index index.html index.htm;
#}
# This is the changed location block
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
}
...
Now I remove the server block that I specified in /etc/nginx/nginx.conf
# Load config files from the /etc/nginx/conf.d directory
# The default server is in conf.d/default.conf
include /etc/nginx/conf.d/*.conf;
# Remove from here
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
}
}
# Remove till here
}
The directive in your configuration (shown below) loads the default server block. This is the reason why you see the nginx welcome page when you request localhost:80 on a newly installed instance of nginx
# Load config files from the /etc/nginx/conf.d directory
# The default server is in conf.d/default.conf
include /etc/nginx/conf.d/*.conf;
You'll find that nginx is already listening on port 80 for localhost so your requests may never reach your newly defined reverse-proxy
Try disabling your default nginx server by opening /etc/nginx/conf.d/default.conf, commenting out the server block there and then restarting nginx

Resources