How to configure Nginx to try two upstreams before 404ing? - nginx

Given an Nginx configuration roughly like this:
upstream A {
server aa:8080;
}
upstream B {
server bb:8080;
}
server {
listen 80;
location #backendA {
proxy_pass http://A/;
}
location #backendB {
proxy_pass http://B/;
}
location / {
# This doesn't work. :)
try_files #backendA #backendB =404;
}
}
Basically, I would like Nginx to try upstream A, and if A returns a 404, then try upstream B instead, and failing that, return a 404 to the client. try_files does this for filesystem locations, then can fall back to a named location, but it doesn't work for multiple named locations. Is there something that will work?
Background: I have a Django web application (upstream A) and an Apache/Wordpress instance (upstream B) that I would like to coexist in the same URL namespace for simpler Wordpress URLs: mysite.com/hello-world/ instead of mysite.com/blog/hello-world/.
I could duplicate my Django URLs in the Nginx locations and use wordpress as a catch-all:
location /something-django-handles/ {
proxy_pass http://A/;
}
location /something-else-django-handles/ {
proxy_pass http://A/;
}
location / {
proxy_pass http://B/;
}
But this violates the DRY principle, so I'd like to avoid it if possible. :) Is there a solution?

After further googling, I came upon this solution:
location / {
# Send 404s to B
error_page 404 = #backendB;
proxy_intercept_errors on;
log_not_found off;
# Try the proxy like normal
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://A;
}
location #backendB {
# If A didn't work, let's try B.
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://B;
# Any 404s here are handled normally.
}

Related

nginx redirect different roots to different ports

After hours of checking documents and stackoverflow, I still cannot figure out how to do this.
this is my nginx.conf:
http {
upstream backend {
least_conn;
server 192.168.77.81:8078 weight=4;
server 192.168.77.231:8078 weight=7 max_fails=1 fail_timeout=1s;
}
upstream static_backend {
server 192.168.77.81:8079;
}
server {
listen 8068;
access_log off;
error_log off;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static/ {
proxy_pass http://192.168.77.81:8079;
}
}
}
events {}
I want to redirect all the http://192.168.77.81:8068/static to http://192.168.77.81:8079/static
but it all results in either 301 Moved Permanently or http://192.168.77.81:8078/static
which drive me crazy
I also have tried alias and root, and they don't work as well
any advice would be very appreciated!
simply just do proxy_pass ~ /static
this "~" took me hours...

nginx redirect url to new pattern

I'm currently switching my blog from Wordpress to Ghost. There is nginx in front of ghost.
After migration i recognized that old urls
http://domain.org/2015/10/some-topic
are migrated like
http://domain.org/some-topic
So date is gone. Anyway there is some backlinking i don't want to loose, but i'm not so familiar with nginx...So what is the best way to redirect from old url style to new?
My curent configuration looks like:
server {
listen 80;
server_name domain.org;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://10.240.0.2:2368;
proxy_redirect off;
}
}
What should be added?. I suppose i need new location but how it should look like?
I would recommend using a map:
map $uri $redirect_topic {
"~^/\d{4}/\d{2}/(?<topic>.*)" $topic;
}
server {
listen 80;
server_name domain.org;
if ($redirect_topic) {
return 301 $scheme://$host/$redirect_topic;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://10.240.0.2:2368;
proxy_redirect off;
}
}
I think you should put into server section:
rewrite ^/[0-9]*/[0-9]*(/.*) $1 last;
But if you've any additional requests maybe would better in a location section (as you wrote).
About more information see on the official nginx documentation.

nginx redirect all http to https with exceptions

I would like to redirect all http traffic to https with a handful of exceptions. Anything with /exception/ in the url I would like to keep on http.
Have tried the following suggested by Redirect all http to https in nginx, except one file
but it's not working. The /exception/ urls will be passed from nginx to apache for some php processing in a laravel framework but that shouldn't matter.
Any suggestions for improvement much appreciated!
server {
listen 127.0.0.1:80;
location / {
proxy_pass http://127.0.0.1:7080;
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-Accel-Internal /internal-nginx-static-location;
access_log off;
}
location /exception/ {
# empty block do nothing
# I've also tried adding "break;" here
}
return 301 https://localhost$request_uri;
}
Nginx finds the longest matching location and processes it first, but your return at the end of the server block was being processed regardless. This will redirect everything but /exception/ which is passed upstream.
server {
listen 127.0.0.1:80;
access_log off;
location / {
return 301 https://localhost$request_uri;
}
location /exception/ {
proxy_pass http://127.0.0.1:7080;
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-Accel-Internal /internal-nginx-static-location;
}
}

Nginx proxy_pass failover to multiple upstream servers

I'm having a hard time finding a solution for nginx proxy_pass failover setup.
I need to proxy certain locations to backend server URL's -
location /Data {
proxy_pass https://backend1.example.com/site1-url;
proxy_set_header X_HOST $host;
}
location /Photos {
proxy_pass https://backend1.example.com/site2-url;
proxy_set_header X_HOST $host;
}
It works as expected, but I need nginx to failover to another server. So the obvious thing would be to use upstream:
upstream servers {
server backend1.example.com;
server backend2.example.com backup;
{
location /Data {
proxy_pass https://servers/site1-url;
proxy_set_header X_HOST $host;
}
location /Photos {
proxy_pass https://servers/site2-url;
proxy_set_header X_HOST $host;
}
..., but this doesn't work. Nginx doesn't understand that the proxy_pass contains upstream.
Is there an elegant way to do this?
Use proxy_pass https://servers and use a rewrite to go to site1-url and site2-url:
location /Data {
rewrite ^ /site1-url/$request_uri? break;
proxy_pass https://servers;
proxy_set_header X_HOST $host;
}
location /Photos {
rewrite ^ /site2-url/$request_uri? break;
proxy_pass https://servers;
proxy_set_header X_HOST $host;
}
WARNING: I've not tested this configuration.

how to reverse proxy via nginx a specific url?

I have a server running at http://localhost:8080 i want a specific url of this server to be proxied by nginx.
For example, i only want http://localhost:8080/test/(.*) to be reverse proxied to http://localhost/test/(.*).
I'm proxing another server to http://localhost/.
What about just a simple location block?
server {
# ... other stuff
location /test/ {
try_files $uri #testproxy;
}
location #testproxy {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
# all your params
}
}
I made it somehow this way and it worked. Thanks for your comment anyway. :)
server {
listen 80;
# ... other stuff
upstream backend1 {
server 127.0.0.1:8080;
}
location /test/ {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass http://backend1/test/;
}
}

Resources