proxy_pass with nginx variable as argument - nginx

i want to use nginx set directive to use a variable as argument of proxy_pass but doing so ends up in a endless 301 Moved Permanently error in chrome when accessing https://foo.de/myleaps with the code below:
example code
user "reverse-proxy" "reverse-proxy";
error_log stderr;
daemon off;
events {}
http {
server {
listen 80;
listen [::]:80;
server_name foo.de;
location /myleaps {
rewrite ^ https://$server_name$request_uri? permanent;
}
} server {
ssl on;
listen 443 ssl;
listen [::]:443 ssl;
server_name foo.de;
ssl_certificate /var/lib/nixcloud/TLS/foo.de/selfsigned/fullchain.pem;
ssl_certificate_key /var/lib/nixcloud/TLS/foo.de/selfsigned/key.pem;
location /myleaps {
set $tttt http://127.0.0.1:3031/myleaps;
# https default flags
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-Proto $scheme;
proxy_pass $tttt;
}
location /myleaps/leaps/ws {
# https websocket default flags
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 36000s;
# required because of CORS
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3031/myleaps/leaps/ws;
}
}
}
using hardcoded values (no set)
when using this:
proxy_pass http://127.0.0.1:3031/myleaps;
instead of:
proxy_pass $tttt;
it works for my example.
so the question is: why does proxy_pass work with an hard coded string but not with using a variable?
motivation
in the reverse-proxy here https://github.com/nixcloud/nixcloud-webservices/blob/be57d526547c66db05595002682525ca62c8f068/modules/services/reverse-proxy/default.nix#L144 the code which generates the proxy_pass is basically hardcoded and if a user wishes to override this it is going to be really complicated. so the idea is to generate 3 variables: ip, port and path and put it into the location scope and let the user later use these. this way i could get rid of the hardcoded proxy_pass directive and the user would be much more flexible in modifying/generating the location record.
so the code could be like this:
set $targetIP = ${location.ip};
set $targetPort = ${toString location.port}
set $targetPath = ${removeSuffix "/" (toString (builtins.toPath (location.path)))};
and the 3 lines above would always be generated into that location record, no matter what. but the code below is dynamically generated and a default implementation could be this:
proxy_pass http://$targetIP:$targetPort$targetPath;
but the user could simply override it by:
nixcloud.reverse-proxy = {
enable = true;
extendEtcHosts = true;
extraMappings = [
{
domain = "example.com";
path = "/";
https = {
mode = "on";
basicAuth."joachim" = "foo";
record = ''
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-Proto $scheme;
proxy_pass http://$targetIP:$targetPort$targetPath
'';
};
}
];
};

it is working using $request_uri instead of hardcoding the proxy_pass path using $targetPath:
set $targetIP 127.0.0.1;
set $targetPort 3031;
proxy_pass http://$targetIP:$targetPort$request_uri;
this code will soon be in nixcloud-webservices!
thanks to irc.freenode.net#nginx#benbrown (Ben Brown) for this solution!

Related

Regex in nginx inside map

I cannot fix routing in nginx for different parts in URI . So if the request has URI starting with de it should pass the traffic to app_b. That does not happen and I'm getting error: invalid URL prefix in "http://"
Here's the config.
map $request_uri $resources_location {
"/" "app_a:1234/";
"^.*de.*$" "app_b:2345/";
}
server {
listen 80;
listen [::]:80;
server_name example.com;
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://$resources_location;
proxy_redirect off;
}
location ~ ^/(assets|public|favicon.ico) {
proxy_pass http://$resources_location;
}
}
How that can be solved (also with a help of map)?

NGINX frontending Kibana not working with "_plugin/kibana/" URI

I'm running the AWS Managed ElasticSearch to collect some logs and have created some Kibana dashboards to visualise the data, all that works fine.
Unfortunately the Kibana plugin included on with the AWS cluster is pretty much open to the world, so I have setup an NGINX reverse proxy to provide authenticated access. This is also working fine if I simply hit the domain URL and specify the full URI to the Kibana plugin. For example:
http://nginx.domain.com/_plugin/kibana/app/kibana works just fine, here in the nginx configuration I am using to achieve that:
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://search-mystuff.ap-southeast-2.es.amazonaws.com/;
proxy_redirect https://search-mystuff.ap-southeast-2.es.amazonaws.com/ /;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}
Rather than providing the full URL, I would like to simply hit the base domain name of the NGINX server, which would then redirect me to the full Kibana URI. So what I would LIKE to do is this:
http://nginx.domain.com
After entering the above URL, I would like to be redirected to the full Kibana URI, so I would end up with a URL like this
http://nginx.domain.com/_plugin/kibana/app/kibana
Here is the nginx configuration I have tried (in various different permutations) that does not work:
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_set_header User-Agent $http_user_agent;
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://search-mystuff.ap-southeast-2.es.amazonaws.com/_plugin/kibana/app/kibana;
proxy_redirect https://search-mystuff.ap-southeast-2.es.amazonaws.com/_plugin/kibana/app/kibana /;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}
With the configuration above, when I browse to http://nginx.mydomain.com the URL is redirected to:
http://nginx.myaws.com.au/_plugin/kibana/app/kibana
This looks like it SHOULD work, however I receive an error in the browser window:
{"statusCode":404,"error":"Not Found"}
I have about 4 hours experience with nginx, so hopefully I'm missing something simple. Any help would be very much appreciated.
Thank you!
Got it, finally!
worker_processes auto;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
server_name localhost;
location / {
proxy_set_header Host https://<endpoint address>.es.amazonaws.com;
proxy_set_header X-Real-IP <nginx ip address>;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header Authorization "";
proxy_pass https://<endpoint address>.es.amazonaws.com/_plugin/kibana/;
proxy_redirect https://<endpoint address>.es.amazonaws.com/_plugin/kibana/ http://<nginx url>/kibana/;
}
location ~ (/app/kibana|/app/timelion|/bundles|/es_admin|/plugins|/api|/ui|/elasticsearch) {
auth_basic_user_file /etc/nginx/.htpasswd;
auth_basic "Auth Required";
proxy_pass https://<endpoint address>.es.amazonaws.com;
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-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Authorization "";
proxy_hide_header Authorization;
}
}
}

Nginx proxy_pass with rewrite in url?

I would like to implement a reverse proxy which redirect request of http://www.dummy.com/foo/bar/test to http://127.0.0.1/hello/world. I have tried to add rewrite before the pass and it seems not working ...
server {
listen 80;
listen [::]:80;
server_name www.dummy.com;
# access_log /var/log/nginx/upstream_log.log
location / {
root /usr/share/nginx/html/dummy;
}
location /foo/bar/test {
rewrite ^/foo/bar/test /hello/world break;
proxy_pass http://127.0.0.1/;
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-Proto $scheme;
access_log /var/log/nginx/upstream_log.log upstream_logging;
}
}
Is there something missing or wrongly configured?
The above config works as expected... The other server was misconfigured when I test the above configuration.

keystonejs behind nginx proxy

I got stack wiht keystonejs behind nginx .
the nginx .conf :
server {
listen 8080;
server_name localhost;
location /wanghuan/ {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000/;
}
location ~ .*\.(img|gif|jpg|jpeg|png|bmp|swf|js|css)$ {
root /Users/macmini/Desktop/test/wanghuan/public;
}
but keystone admin Ui still block ,the static file can't be find ,
how can i set the admin ui static file?
You should just setup a proxy pass to pass all of your arguments to keystone like so:
upstream keystone {
server localhost:3000
}
server {
listen 8080;
server_name localhost;
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_set_header X-NginX-Proxy true;
proxy_pass http://keystone;
proxy_redirect off;
}
location ~ .*\.(img|gif|jpg|jpeg|png|bmp|swf|js|css)$ {
root /Users/macmini/Desktop/test/wanghuan/public;
}
Not sure you are trying to put all of this under {domain}/wanghuan or just {domain} but this nginx config should work if you want the first option just change the location to be /wanghuan
You need to turn keystone.js init block with this additional option
'trust proxy' : true
and your nginx proxy code block just as simple as:
server {
listen 8080;
server_name localhost;
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3000/;
}
}

ERR_TOO_MANY_REDIRECTS while setting up Ghost + Nginx with both HTTP and HTTPS

I'm deploying Ghost (0.7.6) in a VPS using Nginx (1.8.1). To make the dashboard and sign-in page secure, I force any request to use HTTPS when accessing such pages (such as /ghost page). But, for any request to any other page (such as accessing the Ghost blog itself) I want to force it to use HTTP. Ghost is up listening on 127.0.0.1:2368.
Strangely, the result is not as what I expected: Every time I access my blog (let's say the url is a.b), it says that my site has ERR_TOO_MANY_REDIRECTS and it redirects between http://a.b and https://a.b (or between http://a.b/signin and https://a.b/signin). BUT, when I access the admin dashboard (https://a.b/ghost or http://a.b/ghost), it acts as expected (no error, correctly redirects to use HTTPS).
Any help?
My Nginx configuration:
# Configuration for http://a.b
server {
listen 80;
server_name a.b;
location ^~ /ghost { # /ghost should be accessed securely
return 301 https://$host$request_uri;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}
}
# Configuration for http://a.b
server {
listen 443 ssl;
server_name a.b;
ssl_certificate ...;
ssl_certificate_key ...;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers '...';
location ^~ /ghost { # /ghost should be accessed securely
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}
location / { # Force to use HTTP
return 301 http://$host$request_uri;
}
}
Any kind of help would be appreciated :')
https://github.com/TryGhost/Ghost/issues/2796
location ^~ /ghost { # /ghost should be accessed securely
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:2368;
}

Resources