deploying Node.js app for production - node.js

Most of the tutorials I've come across, you set up a Node.js web app by setting the server to listen on a port, and access it in the browser by specifying that port.. However, how would I deploy a Node.js app to be fully accessible by say a domain like foobar.com?

You have to bind your domain's apex (naked domain) and usually www with your web server's ip or it's CNAME.
Since you cannot bind apex domain with CNAME, you have to specify server IP or IPs or load balancers' IPs

Your question is a little vague.. If your DNS is already configured you could bind to port 80 and be done with it. However, if you already have apache or some other httpd running on port 80 to serve other hosts that obviously won't work.
If you prefer to run the node process as non-root (and you should) it's much more likely that you're looking for a reverse proxy. My main httpd is nginx, the relevant option is proxy_pass. If you're using apache you probably want mod_proxy.

I just created an "A record" at my registrar pointing to my web server's ip address. Then you can start your node app on port 80.

An alternative would be to redirect:
http://www.foobar.com to http://www.foobar.com:82
Regards.

Use pm2 to run your node apps on the server.
Then use Nginx to proxy to your node server. I know this sounds weird but that's the way it's done. Eventually if you need to set up a load balancer you do that all in Nginx too.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://APP_PRIVATE_IP_ADDRESS: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;
}
}
This is the best tutorial I've found on setting up node.js for production.
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04
For performance you also setup nginx to serve your public files.
location /public {
allow all;
access_log off;
root /opt/www/site;
}

Related

How To Set Up a Node.js Application for Production on Ubuntu 14.04

I have developed Rest API using Node JS, Express and MongoDb.
I have istalled MongoDB into one machine with Ubuntu Server OS and Node JS App on machine with Ubuntu Server OS.
Now i need to deploy to Production enviroments with a reverse proxy.
I have seen this post as example:
Deploy Node JS
Now my question is: the reverse proxy server using Nginx must be deploy on a separete machine? Instead Nginx is possible to use Apache?
Thanks for your help
You can deploy nginx on same machine.So your setup will be nginx listening to 80 port of the machine for incoming requests and redirecting all requests to you application as per you have specified in nginx configuration.
if you are deploying nginx on same machine and having application 8080. you can do some thing like this.
server {
listen 80;
server_name example.com;
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 if you can configure apache to redirect request to your application you can replace nginx with apache.(but i have not worked with apache so as per me above configurations works.but if you want some help you can read this one link)

nginx or node app using ssl

I have nodejs express sitting behind nginx. Currently everything works fine. I have Nginx implemented with SSL to utilize https, which then simply forwards the request along to the running node application at the specified port. I'm wondering if this is the best way to do it though? Here's what I currently have...
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mysite.somethingelse.com www.mysite.somethingelse.*;
ssl_certificate /path/to/my/cert.pem;
ssl_certificate_key /path/to/my/key.key;
location / {
proxy_pass http://localhost:3000;
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;
}
}
What if I simply implement an https server on the express end? And then proxy the request to that, and let that do all the decoding? Something like this:
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name mysite.somethingelse.com www.mysite.somethingelse.*;
location / {
proxy_pass https://localhost:3000;
proxy_http_version 1.1;
proxy_cert path/to/cert.pem
proxy_key path/to/key.key
}
}
This second version is likely not even correct. But what I'm going for is implementing SSL on the node app rather than letting nginx do it.
Do I gain anything from doing one vs the other?
What's the best practice here... letting nginx or the node app do this?
And, assuming it's better to do it on the node app, what is the correct implementation here of setting of nginx?
Thank you!
In case if you are in pursuit for performance and going to implement load balancing across several node instances, in is a good idea to terminate SSL on a standalone machine(s). But if you are going to run a single instance of your node app and foreseen load is not high, then it is probably simpler to setup SSL in node. Also I would recommend you to refrain from using nginx and switch to NAT (using firewall) because this approach will use less resources.
Another argument in favor of terminating SSL on nginx is documentation and configuration best practices. You should know that configuring SSL is not only about setting up certificate and private key, it's about lots of security considerations about different ciphers, protocols and vulnerabilities. And it is easier to find working solutions, tips and configurations examples for nginx than for node.
So regarding your questions:
It depends on your goals.
It depends on your goals, but I would recommend you currently to use nginx for SSL termination.
I would recommend you to implement NAT instead of nginx in this case.

jHipster dev profile reverse proxy?

I created a skeleton app with jhipster and added some entitles with import-jdl. Now I'm trying to run the dev profile and it hosts it on localhost:8080, which is fine. But I want to proxy it to the public Internet through nginx and put it behind SSL.
Now if I were using Tomcat as an app server, I could set the proxyHost property on the Connector to tell the app server what its public-facing URL is so it generates URLs for the client properly.
But I don't know what app server jhipster uses for the dev profile or how to configure it.
There are a few ways you can go to solve your problem,
The most simplest one is to reverse proxy using nginx, like this:
server {
listen [::]:80;
listen 80;
server_name your-domain.com;
access_log /var/log/nginx/your-app-access.log;
error_log /var/log/nginx/your-app-error.log;
return 301 https://$host:443$request_uri;
}
server {
listen [::]:443 ssl;
listen 443 ssl;
server_name your-domain.com;
access_log /var/log/nginx/your-app-access.log;
error_log /var/log/nginx/your-app-error.log;
ssl_certificate /path/to/ssl/server.crt;
ssl_certificate_key /path/to/ssl/server.key;
keepalive_timeout 70;
add_header Alternate-Protocol 443:npn-spdy/2;
location / {
proxy_pass http://jhipster;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Request-Start $msec;
}
}
upstream jhipster {
server 127.0.0.1:8080;
}
which should work on every nginx.
This expects your app running at port 8080 at localhost, what is the case when you start it locally. This furthermore requires you to install java and more stuff on your server.
A better way is to use the docker option to create docker images. There are a lot of ways to handle with docker images, like public repository as DockerHub as well as private solutions, like GitLab Container registry. At least you can do a trick by serving the registry docker image at some server with ssl, to use this for private registry.
Then you can at least deploy your app to the same nginx configuration as written above, directing traffic to a running docker container. With this, you only need a arbitrary linux distribution with docker and nginx running.
To gain the power of CI/CD systems, you can deploy these images to complex systems like kubernetes, but also to docker swarm (+ Docker Shipyard), or to smaller and easier to setup solutions like Deis or Dokku. You can read this article, which guides you through a setup of GitLab + GitLab CI + Registry + Dokku, where you can deploy your JHipster application using git push origin master
note: I suggest not to use the dev profile in production. To keep update with your application logs, consider specific logback configuration or solutions as JHipster Console (ELK Stack)

nginx reverse proxy redirecting to wrong domain

I'm using this tutorial nginx reverse proxy tutorial to setup a node site with nginx. this is what my nano /etc/nginx/conf.d/mydomain.com.conf looks like
server {
listen 80;
server_name mydomain.com;
location / {
proxy_pass http://localhost:3000;
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;
}
}
The problem is that when I visit my domain, it's redirecting to another domain that I have setup on the same server. I setup that other domain (a static page) using an nginx virtual hosts tutorial that uses server blocks.
One difference I noticed is that the nginx reverse proxy tutorial doesn't do any of this symlinking between sites available and sites enabled which the virtual hosts tutorial does with the server blocks files. The virtual hosts tutorial instructs the reader to create server block files and then enable them like this
sudo ln -s /etc/nginx/sites-available/demo /etc/nginx/sites-enabled/demo
Do I have to do anything to enable the config file when setting up a reverse proxy with nginx? If not, do you know why it's redirecting to the other domain?
/etc/nginx/conf.d/mydomain.com.conf
Let me start with a small explanation on how nginx matches the hosts, quoting from how nginx processes a request
In this configuration nginx tests only the request’s header field
“Host” to determine which server the request should be routed to. If
its value does not match any server name, or the request does not
contain this header field at all, then nginx will route the request to
the default server for this port.
According to your description I would say there's 2 possibilities,
either that this reverse proxy virtual host has a wrong name, so it's not matched and the request is directed to the first virtual host that listens on port 80.
the reverse proxy is correct but the configuration was not loaded.
To fix this double check that this line is correct server_name mydomain.com; and indeed matches the URL you are requesting, then make sure you reloaded nginx settings sudo service nginx reload
The problem was that /etc/nginx/conf.d/mydomain.com.conf hadn't been copied into
/etc/nginx/sites-enabled

Deploying a nodejs app with ExpressJS

So I have a nodejs app running on port 8081:
http://mysite.com:8081/
I want to access it simply by going to http://mysite.com/ so I setup a virtual host with expressjs:
app.use(express.vhost('yugentext.com', app));
That seems too easy, and it doesn't work. Am I confused about how expressjs vhosts work?
if you want to do these via express well, the problem comes from your dns setup, not from the express code.
Add an A entry to your domain like these:
127.0.0.1 localhost *.mysite.com *.www.mysite.com
You should wait to the DNS propagation. (from seconds to hours).
If apache or other web server is running any vhost on port 80 there will be conflicts.
And the other way:
nodejs and express are far away from the performance offered by apache and nginx (vhost/proxy stuff).
Nginx>Apache (fits better with nodejs)
Creates a proxy from mysite.com to mysite.com:8080
On these way nodejs and express handles the ui, methods, httpserver etc, and Nginx or Apache the proxy , vhost, and managing your static assets sooo fast.
check these config here: Trouble with Nginx and Multiple Meteor/Nodejs Apps
I think you're doing app.listen(8081). You should be doing app.listen(80). I have no experience with express vhosts, but you don't need them for this simple use case.
upstream node-apps {
server host_ip_1:3000;
server host_ip_2:3000;
}
server {
listen 80;
server_name localhost;
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://node-apps/;
proxy_redirect off;
}
}
this is my nginx config, proxy pass multiple servers, good luck :p

Resources