proxy pass configuration in nginx - nginx

I am a front end developer and tried my hands in nginx configuration last time which is working fine. The below is the configuration:
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/localhost.access.log;
location / {
#By default route to node.js running on localhost:9000 port
proxy_pass http://localhost:9000;
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;
}
#currently only one server but will have to redirect to n hosts based on a parameter
location /hosts.json {
proxy_pass http://app-host.net:3000;
}
#currently only one server but will have to redirect to n hosts based on a parameter
location /hosts/ {
proxy_pass http://app-host.net:3000;
}
}
Now, I need to redirect to 4 different servers based on a parameter. ie if the city is Bangalore, I need to redirect to bangalore.corp.net:3000 and if the city is NewYork, then I need to redirect to newyork.corp.net:3000 and so on.
Here is somewhat I am expecting:
location /app1/hosts/ {
proxy_pass http://app1-host.net:3000;
}
#But the proxy pass should point to http://app1-host.net:3000/hosts and not http://app1-host.net:3000/app1/hosts
How can we handle such proxy pass in the nginx configuration file. Please let me know.

You have a URL of the form /app1/hosts/foo which should map to http://app1-host.net:3000/hosts/foo. The can be achieved by appending a URI in the proxy_pass directive, which will act like an alias.
location /app1/hosts/ {
proxy_pass http://app1-host.net:3000/hosts/;
}
See this document for details.

Related

Nginx not appending path when using proxy_path

I am trying to use Nginx as a reverse proxy for a few backends. It's probably not relevant, but the backends are all hosted within a single Docker network, and the network is being created using docker-compose.
The backends all have the same endpoints that need to be exposed, so to reduce duplicate configuration lines I am trying to use map.
map $http_host $backend {
host-a.example.com host-a;
host-b.example.com host-b;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
location / {
# there is no DNS resolution if we set proxy_pass targets dynamically,
# use the docker internal DNS server
resolver 127.0.0.11;
proxy_pass "http://$backend:8080/";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The resolver line has been added as Nginx will otherwise give the error: no resolver defined to resolve *hostname*
However with this configuration I am finding that requests are being sent to the wrong path, for example if I send a request to https://host-a.example.com/books or https://host-a.example.com/books/123/front-cover.jpg the page that is returned is always the root of the site (i.e. https://host-a.example.com/), it seems that for some reason proxy_pass is not including the path with the request to the backend server.
Is there a way that I can make this work with map or do I need to create a separate server block for each of the backends that I want to proxy requests to.
From the proxy_pass documentation:
When variables are used in proxy_pass
. . .
In this case, if URI is specified in the directive, it is passed to the server as is, replacing the original request URI.
You should either remove the trailing / (the documentation calls this the optional URI) :
proxy_pass http://$backend:8080;
Or provide the full URL of the request (conveniently available as a built-in variable) :
proxy_pass http://$backend:8080$request_uri;

Nginx proxy_pass trailing slash does not translat location headers

I have a jellyfin server I want to proxy_pass to but when i go to 192.168.1.34/jellyfin/, I'm redirected to 192.168.1.34/web/index.html instead of 192.168.1.34/jellyfin/web/index.html. All I found online is that the trailing slash should take care of this problem but it does not work for me. I can see in the network tab that the redirect is triggered by a Location /web/index.html Header.
server {
listen 80;
server_name 192.168.1.34;
location /jellyfin/ {
proxy_pass http://192.168.1.65:8096/;
}
location /jellyfin/socket/ {
proxy_pass http://192.168.1.65:8096/socket/;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Is there a way to make this work? (I'm only using ipv4) Thanks.

How to rewrite url in nginx after matching the location

I am learning nginx, trying to setup an in-house server. My configuration is:
upstream app{
server app:8000;
}
server {
listen 80;
location /api/app/ {
proxy_pass http://app;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
I want to request nginx with localhost/api/app/admin, but my app can only respond to app:8000/admin. Hence, I want only admin/ to be passed to the application. I tried using rewrite, but was not able to get the desired result.

location "/app" cannot be inside the named location

I want to configure a nginx reverse-proxy server to redirect requests to different servers depending on :
the endpoint
whether it is a plain web request or a websocket upgrade request
I know I can use locations to manage the first point, and named locations to manage the second point, but how can I do both?
server {
listen 80 default_server;
listen [::]:80 default_server;
location /app {
location #web {
proxy_pass http://127.0.0.1:9080/app;
}
location #ws {
proxy_pass http://127.0.0.1:9081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
I get the error message location "/app" cannot be inside the named location "#web"
What am I supposed to do to managed that kind of mixed trafic

Can't nginx proxy pass to kibana in kubernetes

I'm trying to use a proxy pass with nginx to a Kibana pod using a basic auth.
Worked for testing (it's another k8s cluster, but pretty similar, using same namespace, kube-dns, env inside the pods matches and they see each other)
Context: I deploy this via helm at k8s in AWS, the nginx has a Kubernetes LB service type (which basically it's an ELB at AWS with its cname at route53).
If I point nginx pod to kibana-app.kube-system.svc.cluster.local:5601 I see the request at kibana pod from nginx, but returning 404 while trying to go to server.basePath: /api/v1/proxy/namespaces/kube-system/services/kibana-app/
I can access kibana-app pod by getting the url from "kubectl cluster-info" and then checking the logs, the request goes like this:
"method":"get","statusCode":200,"req":{"url":"/app/kibana"
"x-forwarded-uri":"/api/v1/proxy/namespaces/kube-system/services/kibana-logging/app/kibana
Can't find what's going wrong while trying to reach Kibana path from nginx (after doing a basic auth)
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/host.access.log;
location / {
auth_basic "simple auth";
auth_basic_user_file /var/kibana_config/htpasswd;
try_files KIBANA #kibana-app;
}
location #kibanaapp {
return 301 http://kiban-app-url-from-route53/server.basePath;
}
location /api {
proxy_pass https://api.awszone.mydomain/api;
proxy_set_header Authorization "Basic ";
}
}
Also tried to move the proxy_pass statement, removing the return and just doing a proxy_pass from where kibana's pod is listening but either doesn't work, the request never gets to the pod or when the request gets to kibana-app pod, it returns a 404.
Any thoughts?
Thanks!
Update :
I'm almost there, now I can see the "kibana is loading screen" but never finish loading the bundles, json and stuff, nginx pod log:
GET /api/v1/proxy/namespaces/kube-system/services/kibana-logging/bundles/commons.style.css
same request at kibana pod returning 404:
"statusCode":404,"req":{"url":"/app/kibana/v1/proxy/namespaces/kube-system/services/kibana-logging/bundles/commons.bundle.js?v=10146","method":"get","headers":{"host":"kibana.app.env.com","referer":"http://kibana.app.env.com/api "referer":"http://kibana.app.env.com/api"},"res":{"statusCode":404,"responseTime":2,"contentLength":9},"message":"GET /app/kibana/v1/proxy/namespaces/kube-system/services/kibana-logging/bundles/commons.bundle.js?v=10146
my nginx conf:
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/host.access.log;
location / {
auth_basic "simple auth";
auth_basic_user_file /var/kibana_config/htpasswd;
try_files KIBANA #kibana-app;
}
location #kibana-app {
return 301 kibana.app.env.com/server.basePath;
}
location /api {
proxy_pass http://kibana-logging.kube-system.svc.cluster.local:5601;
proxy_set_header HOST $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization "simple auth ";
}
}
"kibana.app.env.com" it's just the FQDN that kubernetes creates at route53 as a CNAME to an ELB which hits the nodes from where nginx/kibana pods are. That's the url I use at the browser and it should reach nginx, ask me for basic authorization and then take me to kibana pod with server.basePath: /api/v1/proxy/namespaces/kube-system/services/kibana-logging Please, ask me something if I'm not being clear, sorry that I can't just copy/paste everything.
Not sure how this is working on the other cluster. So the base path that you mentioned: /api/v1/proxy/namespaces/kube-system/services/kibana-app/ seems like a kube-apiserver base path, and that's the path that a proxy setup using kubectl proxy would do to talk to your applications and services in the cluster.
If you really want to talk from nginx to Kibana inside the cluster you would have to add the kibana-app.kube-system.svc.cluster.local:5601 endpoint to your nginx backend.
Finally, it's working:
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/host.access.log;
location / {
auth_basic "simple auth";
auth_basic_user_file /var/kibana_config/htpasswd;
try_files KIBANA #kibana-app;
}
location #kibana-app {
return 301 /api/v1/proxy/namespaces/kube-system/services/kibana-logging/;
}
location /api/v1/proxy/namespaces/kube-system/services/kibana-logging/ {
proxy_set_header Authorization "simple auth ";
proxy_pass http://kibana-logging.kube-system.svc.cluster.local:5601/;
proxy_set_header HOST $host;
proxy_set_header Referer $http_referer;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
Going to the URL that K8s created at AWS as an ELB (kibana-app.env.com) redirects to /api/v1/proxy/namespaces/kube-system/services/kibana-logging/ which proxy_pass to kibana pod : http://kibana-logging.kube-system.svc.cluster.local:5601

Resources