Nginx per location / pass rewriten uri to proxy_pass - url

What the quickest and cleanest solution if you want to proxy URL request to two different backends via proxypass based on location.
location /app1/ {
alias /var/www/ruby/public;
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_redirect off;
try_files $uri $uri/ #ruby;
}
location #ruby {
proxy_pass http://127.0.0.1:3000;
}
location /app2/ {
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_redirect off;
try_files $uri $uri/ #other;
}
location #other {
proxy_pass http://127.0.0.1:8080;
}
With this config nginx pass "/app1" or "/app2" to proxy and backend doesn't recognize the url/command ..
as for instance would like to pass to http://127.0.0.1:3000 only /messages when accessing http://<nginx>/app1/messages - but in configuration above also pass /app1/ as http://127.0.0.1:3000/app1/messages. Same goes for /app2

Try putting "/" at the end of upstream name
e.g
proxy_pass http://127.0.0.1:8080/;
Please see this post:
How to preserve request url with nginx proxy_pass

Related

The URLs in the content of the page are broken when I use Nginx to proxy pass a subdirectory to a server

I am using proxy_pass in Nginx to redirect /phpmyadmin[/] to a container where PHPMyAdmin is running (the project is available here on Github). The problem is that when I use https://localhost/phpmyadmin/, I get the HTML and content of PHPMyAdmin in the correct way, but, when I drop "/" at the end of the URL, it returns me the HTML with the wrong resource URLs (such as https://localhost/favicon.ico instead of https://localhost/phpmyadmin/favicon.ico). My Nginx config file looks like this:
upstream backend {
server app1:9000;
server app2:9000;
server app3:9000;
server app4:9000;
}
upstream docker_phpmyadmin {
server phpmyadmin:443;
}
server {
server_name localhost;
listen 443 ssl http2;
root /var/www;
location ~ /phpmyadmin {
# (START) some queries don't work when modsecurity is on
modsecurity off;
# (END) some queries don't work when modsecurity is on
# (START) large databases might demand long time and large memory
client_max_body_size 100m;
client_body_buffer_size 10M;
proxy_read_timeout 6000;
proxy_send_timeout 6000;
# (END) large databases might demand long time and large memory
rewrite /phpmyadmin/?(.*)$ /$1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass https://docker_phpmyadmin;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
}
modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/main.conf;
location / {
index index.php;
try_files $uri $uri/ /index.php;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
error_page 404 error.html;
location = /error.html {
root /var/www;
}
location ~* \.(ico|css|js|gif|jpe?g|png)$ {
expires 10d;
}
location ~* \.php$ {
try_files $uri =404;
fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The same issue arises when I try to use MailCow in my project using:
location ~ /mailcow {
rewrite /mailcow/?(.*)$ /$1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass https://docker_nginx_mailcow;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto https;
# proxy_redirect off;
}

How to configure NGINX Location for Multiple Service

I want to configure NGINX to work as a reverse proxy to other Microservices.
I am able to forward the request from NGINX to one of the microservice
if I do curl http://xx.xx.xx.xx:8080/ call did landed on consumer-portal But
its using default location configuration /
when I comment the 1st block and configure the same code for location /consumer-portal and do curl http://xx.xx.xx.xx:8080/consumer-portal
I get :
Cannot GET /consumer-portal
I have more than 10 microservice which I want to call using NGINX.
Below is my nginx.conf file
worker_processes 4;
events {
worker_connections 1024;
}
http {
sendfile on;
upstream consumer-portal {
server xx.xx.xx.xx:9006;
}
upstream publisher-portal {
server xx.xx.xx.xx:9001;
}
server {
listen 8080;
#1st Block
#location / {
# proxy_pass http://consumer-portal;
# proxy_redirect off;
# 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-Host $server_name;
#}
#2nd Block
location /consumer-portal {
proxy_pass http://consumer-portal;
proxy_redirect off;
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-Host $server_name;
}
#3rd Block
location /publisher-portal/ {
proxy_pass http://publisher-portal;
proxy_redirect off;
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-Host $server_name;
}
}
}
Also, Please let me know If I can forward the request using docker container name.
e.g instead of server xx.xx.xx.xx:9006 i want to use server consumer-portal:9006
Please suggest what changes I need to do into .conf file.
location /consumer-portal {
proxy_pass http://consumer-portal;
If your proxy_pass URL is just a domain/IP/hostname and has no URI set then Nginx will pass the full client request URL to the proxy for requests matching the location block. So here your request to
http://xx.xx.xx.xx:8080/consumer-portal will be proxied by Nginx to
http://consumer-portal/consumer-portal
If your proxy_pass URL is a domain/IP/hostname which also has a URI appended then Nginx will replace the matching part of your location block from the original client request with the URI in your directive and then proxy the resulting URL to the upstream server. So if you had proxy_pass http://consumer-portal/new/location; then a request to
http://xx.xx.xx.xx:8080/consumer-portal/account would be proxied by Nginx to
http://consumer-portal/new/location/account
As you want to remove /consumer-portal from the request to the upstream proxy the solution is as simple as adding a trailing slash to your proxy_pass directive, like this:
proxy_pass http://consumer-portal/;

Nginx proxy_pass then try_file

I am setting up a Rails app with nginx in front.
What I want is first to check if the URL makes sense for Rails then serve content of the public folder.
I can't achieve this:
upstream extranet {
server localhost:3000;
}
server {
location / {
try_files #extranet $uri;
root /var/www/extranet/public;
}
location #extranet {
proxy_pass http://extranet;
proxy_read_timeout 90;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;
client_max_body_size 100m;
}
}
I get: *1 rewrite or internal redirection cycle while internally redirecting to "/" error.
It seems like try_files $uri #extranet; works but in my case it feels safer to check the Rails app first because the public folder might change.
try_files checks for the presence of a file on the local file system and cannot respond to the response code from a proxy.
Presumably, the proxy response with a 404 response if the remote page does not exist, which can be intercepted by an error_page statement.
For example:
location / {
proxy_pass http://extranet;
proxy_set_header ...
proxy_set_header ...
proxy_set_header ...
proxy_intercept_errors on;
error_page 404 = #fallback;
}
location #fallback {
root /var/www/extranet/public;
try_files $uri =404;
}
See this document for more.

nginx: remove path from proxy_pass on named location

I have this nginx config to serve a rails app:
location ^~ /api/ {
alias /srv/www/rails/public/;
try_files $uri #unicorn;
}
location #unicorn {
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_redirect off;
proxy_pass http://127.0.0.1:2007;
}
I want to remove /api/ from the start of path before passing it to rails app, but since it's a named location I can't add "/" at the end of proxy_pass directive, how can I remove /api/ before passing request to rails?
Use:
location #unicorn {
rewrite ^/api(.*)$ $1 break;
...
}
See this document for details.

Why I can't access to subdomain through nginx proxy pass?

I wanna to deploy my Ruby on Rails application in my local computer by Nginx and RoR web servers (like Unicorn, Thin or WEBrick).
As shown below, I wanna access to my web-app by post subdomain:
upstream sub {
server unix:/tmp/unicorn.subdomain.sock fail_timeout=0;
# server 127.0.0.1:3000;
}
server {
listen 80;
server_name post.subdomain.me;
access_log /var/www/subdomain/log/access.log;
error_log /var/www/subdomain/log/error.log;
root /var/www/subdomain;
index index.html;
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_redirect off;
try_files /system/maintenance.html $uri $uri/index.html $uri.html #ruby;
}
location #ruby {
proxy_pass http://sub;
}
}
Everything is working fine and when I type post.subdomain.me I can see my RoR app.
Problem: When I use post.subdomain.me url I can't access to my subdomain (request.subdomain returns empty and request.host returns subdomain instaed of subdomain.me). But when I use post.subdomain.me:3000 every things work perfect (I lost half of my hairs to realize that). Why and How can I resolve it?
When you access app with port - you are accessing the rails server directly, not proxied by nginx, this is fine for debug, but usually is not well for production.
Probably host header is not passed over by client, $host defaults to nginx host
Try
location #ruby {
proxy_set_header Host $host;
proxy_pass http://sub;
}
And a 'hardcode'-way: proxy_set_header Host post.subdomain.me;
The proxy_set_header and proxy_redirect directives configure the proxy_pass directive and need to be within the same location block or inherited from the enclosing server block. You need to format your configuration file like this:
location / {
try_files /system/maintenance.html $uri $uri/index.html $uri.html #ruby;
}
location #ruby {
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_redirect off;
proxy_pass http://sub;
}
EDIT: Assuming that nginx is not passing the information to RoR correctly, as #Vasfed suggested, try other values for proxy_set_header Host. There are three other candidates, all with slightly different meanings.
proxy_set_header Host post.subdomain.me;
proxy_set_header Host $server_name;
proxy_set_header Host $host;

Resources