nginx and node js server with ssl - node.js

const https = require(`https`);
const fs = require(`fs`);
const options = {
key: fs.readFileSync(...),
cert: fs.readFileSync(...)
};
https.createServer(options, app).listen(8000);
My node js server looks like this.
does it mean I have to configure nginx like this?
location / {
proxy_pass https://localhost:8000/;
}
Not, proxy_pass to http://localhost:8000/
what makes me confused is that I think network inside the server does'n need ssl.
https server on application server also needs ssl configuration on nginx, right?
I also tried app.listen instead of https.createServer.
My node js app and nginx configuration looks like this.
app.listen(4416);
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
root /root/app;
index template.html;
ssl_certificate ...;
ssl_certificate_key ...;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:4416/;
proxy_buffering off;
proxy_read_timeout 90;
#websocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server{
listen 80;
listen [::]:80;
return 301 https://$host$request_uri;
return 404;
}
In this case, redirection keeps incurred, and I don't know the reason why. What did I miss?
If I did https.createServer(SSL_OPTION, app).listen(4416) instead of app.listen(4416), it doesn't have a connection at all. And if I fix nginx configuration proxy_pass to https://localhost:4416;, then it works well. Things are done well but, I wonder why this is happening.

Related

how to write Nginx config file of two node.js apps in one server?

I have a server where a node.js app is running
Now I want to run another app on the same server
I don't know what changes I should make to my nginx file
Please guide me
this is my nginx file
server {
listen 80;
server_name beranggrup.com , www.beranggrup.com;
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:3445;
proxy_redirect off;
proxy_buffering off;
}
location /images/ {
alias /opt/public/images/;
}
}
server {
listen 443 http2 ssl;
listen [::]:443 http2 ssl;
server_name beranggrup.com;
}

Websocket connection on Google Compute Engine using a custom domain name

I have a websocket server (node.js) which runs fine on localhost and on a previous heroku deployment. I am now migrating to google compute engine and running into some issues.
The websocket handshake is failing returning a 301 error. As pointed out in this answer this can be due to the request going through front end servers that do not support a websocket connection and can be worked around by targeting ws://my_external_gce_ip directly. I am wondering if there is some load balancing configuration I can update so that I can address my backend using the custom domain name.
While I understand the problem, it seems to me that the domain should be resolved to the external ip after a dns lookup so I don't understand the constraint really.
Sorry if this is very obvious. I'm new to GCE and have been googling all day trying to get this. I will paste my code below as well as the NGINX config but I don't think either are particularly helpful as all works fine addressing using the IP
index.js:
/* requirements */
var bodyParser = require("body-parser");
const WebSocket = require("ws");
const http = require("http");
const express = require("express");
const port = process.env.PORT || 3000;
/*
server definition and config
*/
const app = express();
app.use(bodyParser.json());
const server = http.createServer(app);
/*
web socket stuff
*/
const webSocketServer = new WebSocket.Server({
server,
});
webSocketServer.on("connection", (webSocket) => {
console.log("board trying to connect...");
webSocket.on("message", (data) => {
webSocketServer.clients.forEach((client) => {
if (client === webSocket && client.readyState === WebSocket.OPEN) {
client.send("[SERVER MESSAGE]: You are connected to the server :)");
}
});
});
});
/*
activate server
*/
server.listen(port, () => {
console.log(`Server is now running on port ${port}\n`);
});
nginx config
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location \ {
# we're actually going to proxy all requests to
# a Nodejs backend
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;
# I added this baby in
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server
{
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name my_domain; # managed by Certbot
location / {
# we're actually going to proxy all requests to
# a Nodejs backend
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;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/my_domain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/my_domain/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server
{
if ($host = my_domain) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name my_domain;
return 404; # managed by Certbot
}
Thanks very much in advance and sorry if this is a noob question. Total noob when it comes to load balancing
Solved. After a lot more googling I found this thread of people facing the same problem most either using apache servers or elastic beanstalk so not using nginx.
It seems that a lot of people get websockets to "work" using socket.io but they don't really have a duplex connection as it is falling back to long polling.
In my case the answer was simple, I didn't include the server name in my nginx (facepalm) and I may have forgot to include a header. The https forwarding now looks like this (and addressing using my domain works)
location / {
# we're actually going to proxy all requests to
# a Nodejs backend
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;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
}
Don't forget to restart your nginx after you update
sudo systemctl restart nginx

Enabling HTTPS on NGINX for a node js application is not working

I am using a simple "hello world" Express.JS (8080 port) application deployed in Ubuntu Server, with NGINX reverse proxy setup as below.
The application working well for http port but not for https port
nginx version: nginx/1.10.3 (Ubuntu)
OpenSSL 1.0.2g 1 Mar 2016
And my configuration file is like this:
server {
listen 80;
listen 443 default ssl;
server_name localhost;
ssl_certificate /root/mydir/ssl/certificate.crt;
ssl_certificate_key /root/mydir/ssl/private.key;
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;
}
}
The configuration is working fine for http connection for my domain testdomain.com, but completely failing for https://testdomain.com or https://www.testdomain.com
What went wrong with this configuration?
SSL certs are generated by sslforfree.com.
server {
listen 80;
server_name example.com;
# force redirect http to https
rewrite ^ https://$http_host$request_uri? permanent;
}
server {
listen 443;
ssl on;
ssl_certificate /root/mydir/ssl/certificate.crt;
ssl_certificate_key /root/mydir/ssl/private.key;
server_name example.com;
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
....
}

Node js + Nginx + Amazon Linux + SSL

I have a node js application running on AWS linux server with ssl. I wanted to implement nginx to the same. I googled it and read that if I implement ssl in nginx then the node application runs on http. So I configured the nginx conf as follows and ran the node js application with normal http server:
listen 443 ssl;
server_name myserver.com;
ssl_certificate myserver.chained.crt;
ssl_certificate_key myserver.key;
ssl_client_certificate myserver.crt;
ssl_verify_client optional;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header VERIFIED $ssl_client_verify;
proxy_set_header DN $ssl_client_s_dn;
proxy_pass http://127.0.0.1:3000;
}
Now the application is running on http as well as https. I want the nginx to be implemented and through ssl and the application to run only on https.
Is my approach right and what am I missing?
I see you have the application running on port 3000, what you will want to do so that it only runs on https is to block all requests on port 3000 to the server (using a firewall or security group rules in aws), and for every request on port 80 you will want to redirect them to the https version (port 443). Something like this:
server {
listen 80;
server_name my.domain.com;
return 301 https://$server_name$request_uri;
}
I found the above rule in this answer on serverfault.
upstream app
{
server 127.0.0.1:3000;
}
server
{
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
client_header_buffer_size 64k;
large_client_header_buffers 4 64k;
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
location ~ ^/(assets/|images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /var/www/example.com/public/;
access_log off;
expires 24h;
}
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$uri$is_args$args;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

nginx config - forward http to https, forward www.domain.tld to domain.tld and two subdomains

I'm trying to configure nginx to:
http://www.domain.tld --> https://domain.tld
http://domain.tld --> https://domain.tld
http://api.domain.tld --> https://api.domain.tld
The 'www'-webroot serves static HTML (AngularJS) and the API serves an Node.JS app that should 'upstream' from localhost:3000. I guess I'm in the right direction, however it doesn't seem to work for me. Here's what I've got so far:
upstream api_server {
server localhost:3000;
keepalive 64;
}
server {
listen 80;
server_name api.domain.tld;
return 301 https://api.domain.tld$request_uri;
}
server {
listen 80;
server_name *.domain.tld www.domain.tld;
return 301 https://domain.tld$request_uri;
}
server {
listen 443 ssl;
server_name api.domain.tld;
ssl_certificate /etc/ssl/ssl_cert.crt;
ssl_certificate_key /etc/ssl/ssl_key.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
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://api_server/;
proxy_redirect off;
}
server {
listen 443 ssl;
server_name *.domain.tld www.domain.tld;
ssl_certificate /etc/ssl/ssl_cert.crt;
ssl_certificate_key /etc/ssl/ssl_key.key;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
root /var/www/webroot/;
}
Right now this is all in my /etc/nginx/conf.d/domain.tld.conf file.
Any help would be really appreciated.
EDIT:
I've figured it out myself (a bit of help from Tan Hong Tat), so the example is updated.
If you've got any improvements please do tell, I'll update it.
Redirect HTTP to HTTPS in the server block for HTTP. Remove the listen 80 in the HTTPS server block.
server {
listen 80;
server_name domain.tld www.domain.tld;
return 301 https://domain.tld$request_uri;
}
server {
listen 80;
server_name api.domain.tld;
return 301 https://api.domain.tld$request_uri;
}
server {
listen 443 ssl;
server_name domain.tld www.domain.tld api.domain.tld;
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_cache one;
proxy_cache_key sfs$request_uri$scheme;
proxy_pass http://domain_tld_api_server;
}
}

Resources