Deploying a nodejs app with ExpressJS - node.js

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

Related

How do I connect Vue application to server (Node, MongoDB)?

I've been learning frontend development only and just recently went over basics of Nodejs. I know that I would connect to certain port number when developing in Nodejs alone. However, I'm confused about how I would connect Vue application (built with Vue CLI) to backend since npm run serve will automatically connect to port 8080 by default.
My ultimate goal is to connect MongoDB to my application. Current error I'm getting is Error: Can't resolve 'dns'.
TLDR: Could someone please explain in newbie term how I can connect Vue application with MongoDB?
In my opinion, you have two ways of solving this:
First, there is a field called devServer through which you can tweak the configuration of the dev server that starts up when you run npm run serve. Specifically, you want to pay attention to proxy field, using which you can ask the dev server to route certain requests to your node backend.
Second, depending on your setup, you could use a different host altogether to handle backend calls. For example, as you mentioned, the dev server runs on 8080 by default. You could set up your node backend to run on, say, 8081 and all backend requests that you make in your VueJS app will explicitly use the host of <host>:8081. When you decide to move your code into production, and get SSL certificates, you can have a reverse-proxy server like Nginx redirect all requests from say, api.example.com to port 8081.
As for connections to MongoDB, IMO, here's a question you should be asking yourself:
Is it safe to provide clients direct access to the database?
If the answer is yes, then by all means, ensure the mongoDB server starts with its HTTP interface enabled, set up some access restrictions, update the proxy and/or nginx and you're good to go.
If the answer is no, then you're going to have to write light-weight API endpoints in your NodeJS app. For example, instead of allowing users to directly talk to the database to get their list of privileges, you instead make a request to your NodeJS app via GET /api/privileges, and your NodeJS app will in turn communicate with your database to get this data and return it to the client.
Another added benefit to having the backend talk to your database rather than the client, is that your database instance's details are never exposed to malicious clients.
Here's a sample vue.config.js setup that I have on one of my websites:
const proxyPath = 'https://api.example.com'
module.exports = {
devServer: {
port: 8115, // Change the port from 8080
public: 'dev.example.com',
proxy: {
'/api/': {
target: proxyPath
},
'/auth/': {
target: proxyPath
},
'/socket.io': {
target: proxyPath,
ws: true
},
'^/websocket': {
target: proxyPath,
ws: true
}
}
}
}
Here's the nginx config for the same dev server. I quickly pulled what I could from our production config and obscured certain fields for safety. Consider this as pseudo-code (pseudo-config?).
server {
listen 443 ssl;
server_name dev.example.com;
root "/home/www/workspace/app-dev";
set $APP_PORT "8115";
location / {
# Don't allow robots to access the dev server
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|Googlebot") {
return 404;
}
# Redirect all requests to the vue dev server #localhost:$APP_PORT
proxy_pass $scheme://127.0.0.1:$APP_PORT$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 443 ssl;
server_name api.example.com;
set $APP_PORT "8240";
location / {
# Don't allow robots to access the dev server
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|Googlebot") {
return 404;
}
# Redirect all requests to NodeJS backend #localhost:$APP_PORT
proxy_pass $scheme://127.0.0.1:$APP_PORT$request_uri;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

NGINX dns is not working on VPS

I'm a little new to VPS/Linux so please bear with me.
I have a domain name (attendahh.com) pointed to my host's nameservers.
I've set up /etc/nginx/conf.d/attendahh.com.conf as follows:
# the IP(s) on which your node server is running. I chose port 3000.
upstream attendahh.com {
server 127.0.0.1:1999;
}
# the nginx server instance
server {
listen 0.0.0.0:80;
server_name attendahh.com attendahh;
access_log /var/log/nginx/attendahh.log;
# pass the request to the node.js server with the correct headers and much $
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://attendahh.com/;
proxy_redirect off;
}
}
Then I service nginx restart.
I've read a bunch of tutorials and stack answers this is ostensibly all I need to do, but if I go to http://attendahh.com it does not work.
Things to note:
Going to my IP + port in the browser works just fine ( 23.226.227.16:1999 )
I have Cpanel for VPS installed (I tried to set up the DNS in there originally but it didn't work, I've since deleted the dns entry from there but it may still be affecting things)
Apache virtual hosts are commented out in httpd.config.
Any ideas on what I'm doing wrong here? Perhaps there's some conflict between apache and nginx?
- proxy_pass http://attendahh.com/;
+ proxy_pass http://attendahh.com;
Nginx uses its own resolver, it doesn't use the system's resolver (/etc/resolver).
You have to configure it using the resolver directive. If you are not using the resolver directive, then use IP address in the proxy_pass directive.
Source: http://nginx.org/en/docs/http/ngx_http_core_module.html#resolver

Subdomain problems using nginx as a reverse proxy for node apps

I am new to nginx and I'm struggling to get my configuration for a reverse proxy working. I have a node app running on localhost:3010 and I'm trying to serve pages through nginx from this app at the subdomain dev.[sitename].org. Let's just say dev.example.org for readability. Here are the contents of a file I created in sites-available called example.org (is that the correct name for this file?):
server {
server_name www.example.org example.org;
}
upstream app_dev.example.org {
server 127.0.0.1:3010;
}
server {
listen 0.0.0.0:80;
server_name dev.example.org;
access_log /var/log/nginx/dev.example.access.log;
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://app_dev.example.org/;
proxy_redirect off;
}
}
This is mostly based off this related question: Node.js + Nginx - What now? however when I try to open dev.example.org in my browser, Chrome reports that it can't find the page. I can ping dev.example.org and get an IP address, so the server seems to be available, but my nginx configuration incorrect. I created the symlink in sites-enabled and restarted nginx, in case you thought I might have forgotten those steps.
So my thought now is that I'm not referring to the subdomain correctly somewhere, or maybe my file in sites-available is named wrong. Any push in the right direction would be appreciated.
Just to be sure the problem is on nginx try these steps:
Set a test server at port 3030, serving the system doc folder or anything else.
server {
listen 3030
location / {
root /usr/share/doc/;
autoindex on;
}
}
upstream simple_test {
server 127.0.0.1:3030
}
Then use simple_test below as well:
proxy_pass http://simple_test/;
If you see the /usr/share/doc dir listing when you access dev.example.org then your issue is on the node side.
Turned out something was blocking port 80! fixed that and the config as posted above worked

Mixed content error when proxying websocket through nginx with SSL

I am working on a node.js application using express to serve content and socket.io for websocket communication. The setup has been working fine, but now I want to be able to access the websocket via SSL, too. I thought using nginx (which we already used for other stuff) as a proxy was a good idea, and configured it like this:
upstream nodejs {
server 127.0.0.1:8080;
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
server_name _;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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://nodejs;
proxy_redirect off;
}
}
The node.js server is set up like this:
var express = require('express'),
app = express();
// some app configuration that I don't think matters
server = http.createServer(app).listen(8080);
var io = require('socket.io').listen(server);
io.configure(function() {
io.set('match original protocol', true);
io.set('log level', 0);
io.set('store', redisStore); // creation of redisStore not shown
}
Both nginx and node.js run inside a Vagrant box which forwards port 443 (which nginx listens on) to port 4443 on the host system.
With this setup, navigating to http://localhost:4443 (using Firefox 23) gives me access to the files served by Express, but when socket.io tries to connect to the socket, it throws the following error:
Blocked loading mixed active content "http://localhost:4443/socket.io/1/?t=1376058430540"
This outcome is sadly obvious, as it tries to load the JS file via HTTP from inside an HTTPS page, which Firefox does not allow. The question is why it does so in the first place.
Socket.io tries to determine which protocol is used to access the web page, and uses the same protocol in the construction of the above URL. In this case, it thinks it is being accessed over HTTP, which may be the result of being proxied. However, as I understand, setting match original protocol to true in the socket.io config is supposed to help in situations like this, but it does not in my case.
I have found numerous questions and answers here about websocket proxying, but none that deal with this particular issue. So I'm pretty much at wit's end, and would really appreciate some advice.
Change match original protocol to match origin protocol:
io.configure(function() {
//io.set('match original protocol', true);
io.set('match origin protocol', true);
...
}

deploying Node.js app for production

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;
}

Resources