nginx redirection depending on host - redirect

I have two domains website1.com and website2.com linked to my server.
I'm trying to do the following rewrite rules:
http://website1.com/ --> /website1/ (static)
http://website2.com/ --> /website2/ (static)
http://website1.com/app/ --> http://localhost:8080/web-app/web1/
http://website2.com/app/ --> http://localhost:8080/web-app/web2/
The user will be redirected to a static website served by nginx or an application server depending on the url.
Here's what I tried so far:
location / {
root html;
index index.html index.htm;
if ($http_host = website1.com) {
rewrite / /website1/index.html break;
rewrite (.*) /website1/$1;
}
if ($http_host = website2.com) {
#same logic
}
}
location /app/ {
proxy_pass http://localhost:8080/web-app/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($http_host = website1.com) {
rewrite /app/(.*) /$1 break;
rewrite /app /index.html;
}
if ($http_host = website2.com) {
#same logic
}
}
The static part seems to work fine, but the redirection web app part seems to serve index.html no matter what the requested file is.

This is not much of a definitive answer, but rather just my explanation of how I get nginx proxies to work.
root html;
index index.html index.htm;
server {
listen 80;
server_name website1.com;
location / {
alias html/website1;
}
location /app/ {
proxy_pass http://localhost:8080/web-app/web1/
}
}
server {
listen 80;
server_name website2.com;
location / {
alias html/website2;
}
location /app/ {
proxy_pass http://localhost:8080/web-app/web2/
}
}
The issue looks like it's being caused by these rewrites:
rewrite /app/(.*) /$1 break;
rewrite /app /index.html;
Using server blocks with server_names and the alias directive, we can do away with needing to use that much logic. Let me know if there's anything that is still not clear.

I think you're doing it wrong. If there is so much difference between the hosts, it would be cleaner and more efficient to have two distinct configurations, one for each host.
On the other hand, if your intention is to have multiple almost-identical configurations, then the correct way to go about it might be map, and not if.
Back to your configuration — I've tried running it just to see how it works, and one thing that you may notice is that the path you specify within the proxy_pass effectively becomes a noop once the $host-specific rewrite within the same context gets involved to change the $uri — this is by design, and is very clearly documented within http://nginx.org/r/proxy_pass ("When the URI is changed inside a proxied location using the rewrite directive").
So, in fact, using the following configuration does appear to adhere to your spec:
%curl -H "Host: host1.example.com" "localhost:4935/app/"
host1.example.com/web-app/web1/
%curl -H "Host: host2.example.com" "localhost:4935/app/"
host2.example.com/web-app/web2/
%curl -H "Host: example.com" "localhost:4935/app/"
example.com/web-app/
Here's the config I've used:
server {
listen [::]:4935;
default_type text/plain;
location / {
return 200 howdy;
}
location /app/ {
proxy_set_header Host $host;
proxy_pass http://localhost:4936/web-app/;#path is NOOP if $uri get changed
if ($host = host1.example.com) {
rewrite /app/(.*) /web-app/web1/$1 break;
rewrite /app /web-app/index.html;
}
if ($host = host2.example.com) {
rewrite /app/(.*) /web-app/web2/$1 break;
rewrite /app /web-app/index.html;
}
}
}
server {
listen [::]:4936;
return 200 $host$request_uri\n;
}

Related

NGINX not respecting server_name regex

I have this nginx config.. i want it to accept all domains that have the word competitions in it and end with .com.au.. I have tested with a domain name that should NOT be accepted but it reaches the application.. is the server_name being ignore because I'm using a proxy?
server {
listen 80 default_server;
server_name ~^(.+)competitions?(.+)\.com\.au;
access_log /var/log/nginx/$host.access.log;
error_log /var/log/nginx/error.log;
if ($host !~* ^www){
rewrite ^/(.*)$ https://www.$host/$1 permanent;
}
location / {
proxy_no_cache 1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
proxy_intercept_errors on;
recursive_error_pages on;
error_page 404 = #rewrite_proxy;
}
location #rewrite_proxy {
rewrite /(.*) /index.cfm?path=$1;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8888;
}
}
You'd have to remove the default_server from there, because this is a catch-all directive.And you still could setup another one server with the default_server directive, if required.
See How nginx processes a request for a more detailed explanation:
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.

ingress-nginx config use custom variables

I have a nginx conf like below
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
access_log off;
return 200 'Hello, World! - nginx\n';
}
server {
listen 80;
server_name ~^(dev-)?(?<app>[^.]+)\.mysite\.com$;
access_log off;
location / {
resolver 127.0.0.11;
proxy_set_header Host $host;
proxy_pass http://${app}-web;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
I expected that redirecting
dev-blog.mysite.com into service blog-web
dev-market.mysite.com into service market-web
and so on
Is there any way to implement this in k8s ingress-nginx?
No, you would make a separate Ingress object for each (or one huge one, but that's less common). Usually this is semi-automated through either Helm charts or custom controllers.

Nginx Redirect hostname+location

my nginx config uses server_name _; to process all domains in a single server{} block and direct them all to the same codebase sitting in a single folder with a single index.php that sorts out the domain routing. (that's the way the web framework works with 100's of domains within a single cluster - cant change this).
One of the sites has 2 domains. One for each language, let's call them example.com and example.net. This site also has language-specific subfolders, let's call them: /com/ and /net/.
I need to create a redirect that ensures the language subfolder is only loaded on the matching domain.
eg, valid requests:
example.com/com/
example.net/net/
Any other request needs to be redirected based on the subfolder:
example.com/net/ -> example.net/net/
example.net/com/ -> example.com/com/
I cant do it with the framework because the folder contains all static files, so the router is never loaded. Can this be done in the nginx config?
Thank you
update, adding simplified version of my config:
server {
listen 80 default_server;
server_name _;
root /my/app/root;
index index.php index.html;
location / {
try_files $uri /index.php;
}
#PHP
location ~ \.php$ {
try_files $uri = 404;
[fastcgi stuff]
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location = /apple-touch-icon.png {
access_log off; log_not_found off;
}
location = /apple-touch-icon-precomposed.png {
access_log off;
log_not_found off;
}
}
I think that you will need 1 location block per subfolder (but have not tested it):
location /com {
proxy_pass http://upstream:8888/com;
proxy_set_header Host example.com;
proxy_pass_request_headers on;
}
location /net {
proxy_pass http://upstream:8888/net;
proxy_set_header Host example.net;
proxy_pass_request_headers on;
}
Solved it...
location /com/ {
if ($host = 'www.example.net') {
return 301 https://www.example.com$request_uri;
}
index index.html;
}
And the reverse for the other location/domain

why nginx proxy_pass to sub directory is not working?

I am trying to do a proxy_pass to a subdirectory http://ms.server.com:8085/ms. So whenever anyone hit on http://ms.example.com' it should be redirected tohttp://ms.example.com/ms`. I am trying to do that through below configuration
upstream example {
server ms.server.com:8085;
}
server {
server_name ms.example.com;
location / {
proxy_pass http://example/ms;
}
}
Now I am redirecting to "Nginx Test page".
proxy_pass is used to inform Nginx where to send proxied requests at a host level, and does not account for the URI.
What you want to use instead is a return statement, like so:
upstream example {
server ms.server.com:8085;
}
server {
server_name ms.example.com;
location = / {
return 301 http://ms.example.com/ms;
}
location / {
proxy_pass http://example;
}
}
This will redirect requests to the root URL of the server_name http://ms.example.com using a 301 redirect, and all other traffic will be passed through to the defined upstream.

Nginx: Redirect Conditional on Server Name and Sub Domain for Short URLs

I want to redirect conditionally based on the server name, but where I redirect to also depends on the subdomain. So for example, here is my basic config
server {
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443;
server_name company.com compa.ny;
ssl on;
ssl_client_certificate /etc/ssl/certs/godaddy_CA.crt;
ssl_certificate /etc/ssl/certs/wildcard.company.com.crt;
ssl_certificate_key /etc/ssl/private/wildcard.company.com.key;
ssl_prefer_server_ciphers on;
root /var/www/company;
access_log /var/log/nginx/nginx.access.log;
error_log /var/log/nginx/nginx.error.log;
client_max_body_size 8M;
location ^~ /application {
proxy_set_header HOST $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}
I want to have something that looks for the short url host "compa.ny" and redirects to "company.com/shortUrldRedirector" and I also want to include the subdomain, so in dev or qa this will work correctly:
https://compa.ny/abc123 -> https://company.com/shortUrldRedirector/abc123
and
https://dev.compa.ny/abc123 -> https://dev.company.com/shortUrldRedirector/abc123
I see there is a $server_name config variable, but how do I accomplish the above redirects respecting the subdomain?
I would use map construction like this:
map $http_host $long_domain {
default company.com;
dev.compa.ny dev.company.com;
compa.ny company.com;
}
server {
...
return 301 https://$long_domain/shortUrldRedirector$request_uri;
}