Nginx routing on IP address - node.js

I have my domain example.com, so when someone hits on www.example.com or example.com the request is automatically directed to https://example.com - which works fine. However, when I use IP address of the node app 1.2.3.4 it doesn't route to https://example.com which is SSL enabled. If I use the IP address, it shows me the same page but without the padlock icon.
So how do I route a request to https://example.com when someone enters the IP address of node app?
My Node JS APP is hosted on AWS EC2 instance, I have also installed ssl using certbot (LetsEncrpyt). This is my nginx file.
events {
worker_connections 4096; ## Default: 1024
}
http {
include conf/mime.types;
include /etc/nginx/proxy.conf;
include /etc/nginx/fastcgi.conf;
index index.html index.htm;
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 logs/access.log main;
sendfile on;
tcp_nopush on;
server_names_hash_bucket_size 128; # this seems to be required for some vhosts
# Settings for normal server listening on port 80
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com;
root /usr/share/nginx/html;
# location / {
# }
# Redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
}
# Settings for a TLS enabled server.
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name example.com www.example.com;
root /usr/share/nginx/html;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam "/etc/pki/nginx/dhparams.pem";
location / {
proxy_pass http://127.0.0.1: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;
}
}
}

SSL will not work for IP because certificate is issued for the domain name (hence no padlock icon)
You can listen for IP on port 80 (default HTTP port) and redirect to https://example.com
server {
listen 80;
server_name XXX.XXX.XXX.XXX;
return 301 https://www.example.com$request_uri;
}

Related

MERN Stack App with NGINX: Timeout when react app tries to connect to server side API

I have a MERN stack app that I am trying to put into production.
I am able to get the client side running using NGINX as a reverse proxy to port 3000.
The issue I am having is when I am trying to get a response from my server running on port 5000. This is where I have my API to query against my database.
I believe the issue lies in my server block I have set up for my site. Below is an example for my signin endpoint that I am getting a TIMEOUT from. I have replaced my URL with example.com
server {
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.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;
}
location /users/signin {
proxy_pass http://localhost:5000/;
proxy_buffering on;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/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 = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
Any help would be appreciated. I believe I just need help trying to expose these endpoints properly.
Thanks!

Nginx 404 not found for NodeJS App Express Routes

I am trying to run a React App and Node JS app on the same VPS but all api calls to the Express app (NodeJS) are giving me error 404 not found.
I am using nginx and here is my config file:
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name domain_name.org www.domain_name.org;
location / {
# Backend nodejs server
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /user {
# Backend nodejs server
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
location /questions {
# Backend nodejs server
proxy_pass http://127.0.0.1:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain_name.org/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain_name.org/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 = www.domain_name.org) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = domain_name.org) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name domain_name.org www.domain_name.org;
listen 80;
return 404; # managed by Certbot
}
I cannot for the life of me figure out where I'm making the mistake.
It should also be noted that the program works well on my local machine so I don't THINK it's a code or logical error, though please correct me if that's a wrong assumption.
Also the / redirect works fine so I can load the main domain page, just none of the backend/API calls work.
You need 2 reverse proxy server, 1 for the NodeJs backend and the other for the react app.
// backend server
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:4000; # replace port with your backend port
}
}
// react server
server {
listen 80 default_server;
server_name example.com;
location / {
proxy_pass http://localhost:4000; # replace port with your react port
}
}
In your react project use the backend domain api.example.com in your axios or fetch api request... You can configure the ssl certificate... I didn't do that to make the answer minimal and clear...
I also advice you use process manager like PM2 on your backend and react

https www to non www (NGINX)

Im new to all this, but how do i redirect my from www to a non-www. I have tried multiple ways to fix it in NGINX but no mater how i change it, there is still a www and an non-www site. The payment gateway is redirected to a non-www website after a transaction.
server {
server_name example.com www.example.com;
location / {
proxy_pass http://123.0.0.1:5000;
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_redirect off;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dineshudayan.tech/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dineshudayan.tech/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 = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name www.example.com;
return 404; # managed by Certbot
}
server {
listen 80;
server_name admin.example.com www.admin.example.com;
location / {
proxy_pass http://123.0.0.1:8000;
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_redirect off;
}
}
#richard-smith is right; here's a fully worked example with some comments:
# Your default server - assuming DNS is set up correctly
# will serve http & https requests for any *.example.com
# hosts and redirect to them to https://example.com
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/dineshudayan.tech/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dineshudayan.tech/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# redirect all requests to https://example.com
return 301 https://example.com$request_uri;
}
# http server for example.com
# - will redirect requests to https://example.com
server {
listen 80;
server_name example.com;
# redirect all requests to https://example.com
return 301 https://example.com$request_uri;
}
# Your example.com https server
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/dineshudayan.tech/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dineshudayan.tech/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

redirect example.com:3000 to example.com

redirect (301) https://example.com:3000 to https://example.com, while 3000 port accessible only through IP:3000 and NOT through example.com:3000
Using Express.js app on port 3000.
Using nginx to proxy localhost:3000 with example.com.
And now https://example.com:3000 is not accessible (in chrome:
ERR_CONNECTION_CLOSED), but IP:3000 is accessible.
The problem is - search engines indexed almost all
https://example.com:3000 pages and these pages aren't accessible.
As 3000 port is already taken by nodejs, in nginx I cannot write:
server {
listen 3000;
server_name example.com;
return 301 https://example.com$request_uri;
}
nginx conf:
upstream nodejs {
ip_hash;
server localhost:3000;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server;
server_name example.com;
listen [::]:443 ssl default_server;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
include /etc/nginx/snippets/letsencrypt-acme-challenge.conf;
location = /robots.txt {
root /root;
allow all;
log_not_found off;
access_log off;
}
location ~* \.(?:css|js)$ {
root /root;
expires 9d;
add_header Cache-Control "public, max-age=7200";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
# Optional: Don't log access to assets
access_log off;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|flv|swf)$
{
root /root;
expires 365d;
access_log off;
}
# #nodejs
location / {
add_header Cache-Control "private";
add_header Vary "Cookie, User-Agent";
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
include /etc/nginx/proxy_params;
proxy_pass http://nodejs;
}
}
How https://example.com:3000 => https://example.com
and restrict outer access to 3000 port (remain only localhost:3000)?
Add one more server block like the following:
server {
listen EXTERNAL_IP:3000 ;
server_name example.com;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;
include /etc/nginx/snippets/letsencrypt-acme-challenge.conf;
return 301 https://$server_name$request_uri;
}
Note, that application should listen to the only 127.0.0.1:3000, or you may face "address already in use".
In this case all incoming connections will be established with nginx, which redirects users accordingly to your rule.
In case you want to restrict access to port 3000, you may use any firewall. Example for iptables:
iptables -I INPUT -p tcp -i eth1 --dport 3000 -j DROP
But this will close access to https://example.com:3000 too.

Nginx server IP on droplet redirect to specific domain

I have 2 domains running with nginx on a DigitalOcean Droplet
Domain1 is an node app proxypassing to localhost:3000.
Works great!
Domain2 is a static site working great too.
However whenever I load the server IP (without the port 3000), I always get redirected to domain1 (node app).
Domain1 is a sort of a private site, whereas domain2 is a public blog.
My question is what do I have to change for people to get redirected to domain2 whenever they load the IP in order to protect domain1 from beeing easily reachable. (The VPS IP is easy to look up)
Here are the "sites-available" files :
Node App :
server {
listen [::]:80;
listen 80;
server_name www.domain1.com domain1.com;
# and redirect to the https host (declared below)
return 301 https://domain1.com$request_uri;
}
server {
listen 443;
server_name domain1.com www.domain1.com;
ssl on;
# Use certificate and key provided by Let's Encrypt:
ssl_certificate /etc/letsencrypt/live/domain1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain1.com/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
And the static one :
server {
listen [::]:80;
listen 80;
server_name www.domain2.com domain2.com;
root /var/www/html/domain2;
index index.html index.htm;
return 301 https://domain2.com$request_uri;
}
server {
listen [::]:443 ssl;
listen 443 ssl;
root /var/www/html/domain2;
index index.html index.htm;
ssl_certificate /etc/letsencrypt/live/domain2.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain2.com/privkey.pem;
}
Any help/hint is appreciated, thank you in advance!
So both your domains are listening on port 80. When your nginx server receives a request, it then checks the domain before determining its route... but because there is no domain to check when you just type in the ip address, it will default to the first listed server (which i'm guessing is domain1)
you can circumvent this by declaring a default server, or switching the order in which they are listed.
I hope i could be of help. A nice little reference http://nginx.org/en/docs/http/request_processing.html

Resources