Redirect to two ports using Nginx - nginx

I have two angular apps running on different ports. I need to access app1 when the user calls https://url and app2 when the user calls https://url/admin. I tried adding location block to the Nginx config as below but the request is directed to app1 with the /admin added.
server {
# listen 80 default_server;
# listen [::]:80 default_server ipv6only=on;
listen 443 ssl;
root /usr/share/nginx/html;
index index.html index.htm;
server_name fr.techolution.com;
ssl_certificate /etc/nginx/ssl/url_com.crt;
ssl_certificate_key /etc/nginx/ssl/myserver.key;
location / {
proxy_pass http://192.168.2.81:8083;
}
location /admin/ {
proxy_pass http://192.168.2.81:4200;
}
}

Both requests https://url and https://url/admin will be proceeds in the location:
location / {
proxy_pass http://192.168.2.81:8083;
}
Looks like you should remove slash from your second location:
location /admin {
proxy_pass http://192.168.2.81:4200;
}

Related

How to prevent redirects on nginx when domain in host header does not match domain in request url?

I have nginx running on my home server at keepsecret.ddns.net. When I request e.g. keepsecret.ddns.net/foo/ it returns to me keepsecret.ddns.net/foo/index.html. So far, so good.
Now I am trying to treat my home server as an upstream server. In front of that upstream server is a remote proxy server at www.mydomain.com. When I request e.g. www.mydomain.com/foo/index.html, it is returned to me no problem. However, when I request www.mydomain.com/foo/, nginx first issues a 301 redirect so that I then get sent to keepsecret.ddns.net/foo/, revealing my home IP Address :(
I have no idea why nginx behaves this way. My only guess is that it has something to do with the fact that the domain in the request host header does not match the domain in the request url.
Questions in summary:
Why does nginx do this?
How can I prevent nginx performing this redirect so that I always remain on www.mydomain.com?
Here is the salient part of my config for reference:
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 / {
try_files $uri $uri/ =404;
}
}
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name keepsecret.ddns.net www.mydomain.com;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/keepsecret.ddns.net/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/keepsecret.ddns.net/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 = keepsecret.ddns.net) {
return 301 https://$host$request_uri;
}
if ($host = www.mydomain.com) {
return 301 https://$host$request_uri;
}
listen 80 ;
listen [::]:80 ;
server_name keepsecret.ddns.net www.mydomain.com;
return 404; # managed by Certbot
}
NGINX will be doing an internal redirect to the index.html file in all cases, but it seems to get externalised when the server_name does not match the primary server_name. I suspect that changing the server_name order so that your public (proxied) name is first may get rid of that behaviour.
The alternative would be to focus on the reverse proxy, and take a look at proxy_redirect to make the reverse-proxy rewrite location headers for you.
See: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

Different prefix path to different hosts with nginx

I would like to achieve the following with nginx. There is one domain with different paths. Each path should proxy the request to a host on different ports:
https://example.com/path1 -> 10.0.0.1:8081
https://example.com/path2 -> 10.0.0.1:8082
https://example.com/path3 -> 10.0.0.1:8083
Something like this did not work:
location /path1 {
proxy_pass http://10.0.0.1:8081;
}
location /path2 {
proxy_pass http://10.0.0.1:8082;
}
location /path3 {
proxy_pass http://10.0.0.1:8083;
}
Is this scenario possible?
EDIT:
This is the config right now on the nginx server
server {
server_name example.com;
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /some/path/fullchain.pem;
ssl_certificate_key /some/path/privkey.pem;
ssl_dhparam /some/path/ssl-dhparams.pem;
location /path1 {
proxy_pass http://10.0.0.1:8081;
}
location /path2 {
proxy_pass http://10.0.0.1:8082;
}
location /path3 {
proxy_pass http://10.0.0.1:8083;
}
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
}
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
return 404;
}
With this config the prefix path gets removed while loading the site.
https://example.com/path1/some/url -> https://example.com/some/url

Nginx TLS-SNI: Use hostname dependent SSL for HTTPS

I need to use two different ssl certs with nginx pointing to the same app.
https://domain1.com points to 1.1.1.1
https://domain2.com points to 1.1.1.1
.
.
.
.
https://domainN.com points to 1.1.1.1
Tried the following:
server {
listen 80;
server_name domain1.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name domain1.com;
root /app/dist;
index index.html;
ssl_certificate /etc/nginx/ssl/d1/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/d1/private.key;
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
server_name domain2.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name domain2.com;
root /app/dist;
index index.html;
ssl_certificate /etc/nginx/ssl/d2/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/d2/private.key;
location / {
try_files $uri $uri/ /index.html;
}
}
This doesn't work, it just loads the first cert resulting in invalid cert when accessed using the second domain.
The domain certs can't be combined.
I can't spin two different instances for nginx as the case needs to help me out with n-Domains pointing to same IP preferably using one nginx server.
Is there a way out?
Thanks to Richard Smith for pointing out just the right stuff!
So, to setup nginx to use different cert-key pair for domains pointing to the same nginx we have to rely on TLS-SNI (Server Name Indication), where the domain name is sent un-encrypted text as a part of the handshake. This helps nginx to decide which cert-key pair to use for the incoming secure request.
More can be read about SNI here.
Moving on to the configuration.
server {
listen 80;
server_name domain1.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name domain1.com;
root /app/dist;
index index.html;
ssl_certificate /etc/nginx/ssl/d1/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/d1/private.key;
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 80;
server_name domain2.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name domain2.com;
root /app/dist;
index index.html;
ssl_certificate /etc/nginx/ssl/d2/certificate.crt;
ssl_certificate_key /etc/nginx/ssl/d2/private.key;
location / {
try_files $uri $uri/ /index.html;
}
}
The above config forwards HTTP (80) for both domain1 and domain2 to respective HTTPS (443) server blocks, where respective cert-key pairs are loaded.
The HTTPS (443) request is handled directly.
nginx decides which block to hit by picking the server name using SNI.

nginx host default for IP

I have the following default configuration file in nginx:
server {
listen 80;
root /home/d/www;
index index.php index.html index.htm;
server_name localhost;
Recently I added a file to host a specific domain, like:
server {
listen 80;
root /home/d/sites/dom
index index.html index.htm;
server_name dom.co www.dom.co;
After adding this, when loading the public server IP would be routed to this domain configuration folder, /home/d/sites/dom
How can the IP be directed to the default root?
There's listen 80 default; for requests without Host header (if none set - the first one is used)
For requests with unrecognized host - special server_name _; matches
To add to Vasfed's answer, my block are:
/etc/nginx/sites-available/yourdomain
server {
listen 80;
root /www/sites/**yourdomain**;
index index.html index.htm;
server_name **yourdomain**.com www.**yourdomain**.com;
}
/etc/nginx/sites-available/default
server {
listen 80 default_server;
root /www;
index index.php index.html index.htm;
server_name _;
}
These two files need to by sym-linked to sites-enabled.

Too many redirects - changing naked url -> www.example.com

I've changed my conf file so that when a user types in the domain without www it redirects to the domain with www:
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
I also wish for my https for anything under /user
I get the error of too may redirects, where am I going wrong?
So I have:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /var/www/example.com/site;
index index.html index.htm;
# Make site accessible from http://localhost/
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
location /user {
rewrite ^ https://$http_host$request_uri? permanent;
}
}
For port 443:
server {
listen 443;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
root /var/www/example.com/site;
index index.html index.htm;
ssl on;
ssl_certificate //path here
ssl_certificate_key //path here
location / {
rewrite ^ http://$http_host$request_uri? permanent;
}
location /user {
}
}
With
listen 80 default_server;
you are telling nginx that this server block is the default server for all http requests regardless of the server name.
The directive
return 301 $scheme://www.example.com$request_uri;
sets nginx to redirect all incoming traffic for this server block to www.example.com. That redirected traffic hits the same server block again (default server) and the process repeats itself, hence a redirect loop.
To fix this change your config file and add a second server block:
server {
listen 80;
listen [::]:80 ipv6only=on;
server_name www.example.com;
#rest of your config
[...]
}
server {
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
Port 80 can be left out, as it is the default, in case you are wondering.
The same principle applies to traffic for 443 (in the redirect block you however must give the port and ssl specific configuration).

Resources