NodeJS multiple websites - node.js

I have been searching the Internet for a week now trying to find a good solution for this. First I read about http-master but I have been having issues installing it. Then I saw a few others that didn't have the features and ease of configurations. Or the answers were all outdated
We want to develop website in NodeJS, currently have three, two for test/dev and one for production. Each of these are hosted on the same server, currently an Apache server with the same domain name but different ports. We have another website we are working on as well with a different domain name.
Question is, what is the best way to use NodeJS to serve all the sites and more? Going forward we want to develop all applications in NodeJS.
Server Specs:
Windows Server 2012 R2
Two Cores
4 GB RAM

You want to use a reverse proxy. nginx is a good choice because configuration is so simple. But the same can also be achieved with apache.
Basically you just run each application under a different port, and based on domain name proxy over requests. Here's an example setup using nginx.
## Upstream www.example.com ##
upstream examplelive {
server 8081; # nodejs server running on port 8081
}
## Upstream dev.example.com ##
upstream exampledev {
server 8082; # nodejs server running on port 8082
}
## www.example.com ##
server {
listen 80;
server_name www.example.com;
access_log /var/log/nginx/log/www.example.access.log main;
error_log /var/log/nginx/log/www.example.error.log;
## send request back to examplelive ##
location / {
proxy_pass http://examplelive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
## dev.example.com ##
server {
listen 80;
server_name dev.example.com;
access_log /var/log/nginx/log/dev.example.com.access.log main;
error_log /var/log/nginx/log/dev.example.com.error.log;
location / {
proxy_pass http://exampledev;
proxy_set_header Host static.example.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
The below apache example should work.
<VirtualHost *:80>
ServerAdmin admin#example.com
ServerName www.example.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass http://localhost:8081/
ProxyPassReverse http://localhost:8081/
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerAdmin admin#dev.example.com
ServerName dev.example.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass http://localhost:8082/
ProxyPassReverse http://localhost:8082/
</Location>
</VirtualHost>

My preferred way of hosting multiple domains has always been to use vhost with Express, which allows you to match different domain names.
var mailapp = connect()
var staticapp = connect()
// create main app
var app = connect()
// add vhost routing to main app for mail
app.use(vhost('mail.example.com', mailapp))
app.use(vhost('assets-*.example.com', staticapp))
If you don't want to go through the hassle of getting multiple domains pointing to this server, I find that using multiple sub domains on one primary name (e.g. foo1.bar.com, foo2.bar.com and using a CNAME record with your DNS to point to those subdomains is very effective.

Related

Which is the best way to install Nginx And apache together in ubuntu 16.04

I have a VPS server and try to install Apache and Nginx to work together in Ubuntu 16.04 but with different server Names and domains.
So, I have apache to port 8000 and nginx to port 8080.
Nginx do go to 8080 port because use NodeJs and this uses behind the route https://localhost:8080/
Apache uses Laravel 5.5 and PHP.
I have already configure to Apache
/etc/apache2/sites-available/000.default.conf
<VirtualHost *:8000>
ServerName www.myanotherdomainname.com
ServerAdmin webmaster#localhost
DocumentRoot /var/www/laravel/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
/ect/apache2/ports.conf with Listen 8000
For Nginx in /etc/nginx/sites-available/default
location / {
proxy_pass http://localhost:8080;
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;
}
And
server {
if ($host = www.mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name geckode.la www.mydomain.com;
return 404; # managed by Certbot
}
In www.mydomain.com, the script.js run by NodeJs works fine
But in www.myanotherdomainname.com, return 404 Not Found nginx/1.10.3 (Ubuntu)
It doesn't even seem to run apache
I need to know the best way to run apache and nginx with Nodejs.
Apache status and Nginx are running without any problem.
Thanks
It's just doing what you told it to do. Let's run through your config:
if ($host = www.mydomain.com) - Nope...
if ($host = mydomain.com) - Still nope...
return 404; - OK, Ooops, I mean HTTP/1.1 404 Not Found

Nginx Proxy under multiple locations multiple server

I am trying to setup Nginx Proxy for multiple application from multiple servers.
server {
listen 80;
listen 443 ssl;
server_name 192.168.2.28;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
location /dashboard/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_connect_timeout 300;
port_in_redirect off;
proxy_pass http://192.168.1.250/;
}
}
While running https://192.168.2.28/dashboard in browser I am getting the only root files i.e /favicon.png But inside subfolders like js/css are not resolving with location.
How to resolve domain with location with inside directories. I also attached the screenshot. Please, anyone, check and resolve.
Nginx SSL proxy error
if i understand your problem correctly, you want nginx to answer requests for static files directly while proxying everything else to your django-backend.
try adding this to your server config:
location /static/ {
alias /path/to/static/directory/;
}
as described in detail here
in case you want a location to represent a remote path,
nginx can rewrite requests like so:
location ~ /static/ {
rewrite (.*)/(.*) http://external.tld/static/$2;
}
more on that option here

nginx reverse proxy with nodejs and apache over SSL

I have been trying for a long time to set up a reverse proxy with nginx that works with both nodejs over ssl on port 3000 and apache over ssl on port 443. I have tried so many things that my conf files probably have tons of errors. My most recent attempt had this as the /etc/apache2/sites-enabled/000-default.conf:
<VirtualHost *:443>
# The ServerName directive sets the request scheme, hostname and port t$
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin admin#test.com
DocumentRoot /var/www/html/public
SSLEngine on
SSLCertificateFile /var/www/certs/test_com.crt
SSLCertificateKeyFile /var/www/certs/test_com.key
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
And my nginx configuration looks like this:
server {
listen 80;
access_log /var/log/nginx/secure.log;
error_log /var/log/nginx/secure.error.log;
server_name test.com;
ssl on;
ssl_certificate /var/www/certs/test_com.crt;
ssl_certificate_key /var/www/certs/test_com.key;
location / {
proxy_pass https://127.0.0.1:3000;
}
location /public {
proxy_pass https://127.0.0.1:443;
root /var/www/html/public; //this is where I keep all the html files
}
}
When I run netstat -tulpn I get:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::3000 :::* LISTEN -
udp 0 0 0.0.0.0:68 0.0.0.0:*
This is my first time setting up a server like this so I would really appreciate it if someone could explain how reverse proxies are supposed to work with a nodejs server that uses webpages from an apache instance over ssl.
I'm not sure how this works, but if I had to guess logically, I would want an nginx instance listening on port 80 that redirects all http traffic to https traffic. I would want apache configured on port 443 so I would be able to browse to my css stylesheet https://test.com/assets/css/stylesheet.css and be able to use that as a path in my node server.
I found this in my searches but was unable to correctly implement it:https://www.digitalocean.com/community/questions/how-to-setup-ssl-for-nginx-and-apache
I know I'm not explaining it very well, but I hope someone is able to understand what I need and help me out. Thanks!
Yes this sounds confusing. It is very common to have static assets served directly from nginx, then reverse proxy all other requests to some backend (node on 3000).
I am very confused by the need for Apache.
If you really need Apache this is how you can do it.
First, you said you want nginx to listen on port 80 and just redirect all http traffic to https, configure your nginx like this.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
Thats it for nginx.
Now for Apache, you need mod_proxy, it will listen on 443 and handle TLS termination, then proxy requests to node listening on 3000
<VirtualHost *:*>
# your config here...
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html
I'm not sure why you want to do it this way, if you can, I'd suggest only using nginx to listen on 80, redirect to 443, handle TLS termination, serve static assets, and reverse proxy to your backend. It's much simpler to set up.
example
untested nginx config
# replace 'domain.com' with your domain name
# http server, redirects to https
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://example.com$request_uri;
}
# https server
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
ssl on;
# replace this with your cert+key path
ssl_certificate /etc/ssl/private/YOUR_CERT.crt;
ssl_certificate_key /etc/ssl/private/YOUR_SERVER_KEY.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:20m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
ssl_stapling on;
ssl_stapling_verify on;
# replace 'node-app' with your app name
access_log /var/log/nginx/node-app.access.log;
error_log /var/log/nginx/node-app.error.log;
location / {
# the path to your static assets
root /var/www/your-app/public;
try_files $uri $uri/ #nodebackend;
}
# all requests to locations not found in static path
# will be forwarded to the node server
location #nodebackend {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:3000;
proxy_redirect off;
}
}

Pretty url of a MEAN-stack application in nginx

(* As some comments recommended, I removed index.ejs and use index.html in the project by following this answer. So I have adjusted my OP *)
I develop in Mac with apache a MEAN-stack application that can be requested by
https://localhost:3000/#/home. In production with a nginx server, the application can be requested by
https://www.myapp.io/#/home. The fragment-identifier # is needed in all cases because of angular ui-router.
So I wanted to make pretty url without # (eg, https://www.myapp.io/home, https://localhost:3000/home) work. I have done the following:
1) added $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') in app.config(['$stateProvider'....
2) added <base href="/" /> in index.html
As a result, https://localhost:3000/#/home changes automatically to https://localhost:3000/home in the browser bar, similarly for https://www.myapp.io/#/home.
However, directly entering https://localhost:3000/home or https://www.myapp.io/home in the browser will raise an error (I don't know how to turn previous <h1><%= message %></h1><h2><%= error.status %></h2><pre><%= error.stack %></pre> in error.ejs to error.html, so I don't have more details).
So now, the goal is to make https://localhost:3000/home and https://www.myapp.io/home work.
By following this thread, I added the follows to app.js:
app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));
app.all('/*', function(req, res, next) {
res.sendFile('index.html', { root: __dirname });
});
And in apache of mac, here is my httpd-vhosts.conf, after restarting apache,
https://localhost:3000/home still returns an error.
<VirtualHost *:443>
ServerName localhost
DocumentRoot "/Users/SoftTimur"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/apache2/ssl/localhost.crt
SSLCertificateKeyFile /etc/apache2/ssl/localhost.key
<Directory "/Users/SoftTimur">
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
</VirtualHost>
In production, here is the nginx server block. After restarting nginx, https://www.myapp.io/home still returns an error.
server {
listen 443 ssl;
server_name myapp.io www.myapp.io;
ssl_certificate /etc/letsencrypt/live/myapp.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.io/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:EC$
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
index index.html;
root /opt/myapp
location / {
try_files $uri $uri/ /index.html;
}
location ~ /.well-known {
allow all;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Accept-Encoding "";
proxy_set_header Proxy "";
proxy_pass https://127.0.0.1:3000;
# These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove sock$
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Could anyone help?
I think the better question you should be asking yourself is why don't you have index.html? Perhaps I've been asleep for too long, but browsers aren't really capable of executing JavaScript by itself on a webpage, without an underlying DOM from an HTML document.
Once you've got that figured out, you might as well succeed with the official configuration suggestion from angular-ui on GitHub.
Remove the nginx configuration you added. This can be achieved by performing the following:
There are 2 things that need to be done.
Configuring $locationProvider
Setting our base for relative links
See the following link for more detailed instructions on how to accomplish this:
Pretty URLs in AngularJS: Removing the #
For Angular 1.6 you will also need to change the hashPrefix:
appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('');
}]);
I know in your question you stated that you had already done these two steps, but if you follow this tutorial perfectly it will work as I have tested this on my own Angular application (which is also hosted thru nginx).
To go with the server configuration route, I would recommend following this link:
AngularJS with Pretty URLs: Removing the # in Amazon S3
Additionally, here is the actual server configuration changes to make.
And lastly, I think you're mistaken with regard to how ejs works. It requires either HTML bootstrapping (after all, you must have some sort of index.html, with something like <script src="https://npmcdn.com/ejs/ejs.min.js"></script>), or processing on the server (e.g., with nodejs and/or friends).

What is the equivalent value for apache configuration

I need to convert following nginx rule to Apache configuration.
can anyone help me.
location /chat {
rewrite /chat(/.+)$ $1 break;
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_buffering off;
proxy_send_timeout 310;
}
Have a look at the mod_proxy documentation, I think the ProxyPassMatch directive is of interest.
I would convert them to Apache2 like:
ReWriteEngine on
ProxyPreserveHost On
ProxyPass "/chat" "http://localhost:8000" flushpackets=on
ProxyPassReverse "/chat" "http://localhost:8000"
ProxyTimeout 310
in your <VirtualHost *:443> or <Location /chat> section

Resources