I'm trying to host multiple Node JS servers proxied through Nginx, which is working correctly. One server is hosted at '/', with another hosted at, for example, '/one'. The relevant Nginx config for this setup is below.
upstream host_com {
server 127.0.0.1:3000;
keepalive 8;
}
upstream one_host_com {
server 127.0.0.1:3010;
keepalive 8;
}
server {
listen 80;
access_log /var/log/nginx/host.log;
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://host_com/;
proxy_redirect off;
}
location /one {
rewrite ^(/one)+/(.*)$ /$2 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $proxy_host; #$http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://one_host_com/;
proxy_redirect off;
}
}
However, when I do an AJAX call from the '/one' testbed, like below:
$.getJSON( '/get_stuff', function(data) { .. });
The post goes to '/get_stuff' when I want it to go to '/one/get_stuff'. How can I get Nginx to direct to NodeJS but still maintain the location? Is there a better way to implement this?
Try removing the leading slash in your JavaScript, e.g. $.getJSON( 'get_stuff', function(data) { .. });. By including the leading slash you are asking for a path at the root of the domain but I think you want the path relative to the url you are presently at.
Related
I have an auth_request in my /protected/ path. Everything works fine so far. But I want that every request that includes /protected/ for example /protected/application1 and /protected/application2 will be go first through the /protected/ location with the authentication and if this is passed go to the further location.
I have this so far but it doesn't seem that the authentication has any impact of the route.
So when I call /protected/ everything works as expected, when I call /protected/application1 it doesn't matter if the authentication succeeds or not.
This is part of my config:
location /protected/application1 {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:4501;
}
location /protected/application2 {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:4502;
}
location /protected/ {
auth_request /auth;
auth_request_set $auth_status $upstream_status;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:4500;
}
location = /auth {
internal;
proxy_pass http://localhost:8081/welcome;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
Do you have any suggestions?
Thank you very much!
I have a sample app which correctly secures the rest api locally without nginx. Now when I put this in production behind a nginx proxy it does not work. No errors. It allows all request.
Front end serer with ssl is https://frontend.com
Back end server with ssl is https://backend.com
Keycloak proxy forward is true
Front end server(node server on 9000) <-> NGINX <-> Keycloak (running on 8180)
nginx file sample
upstream keycloak_server {
server localhost:8180;
}
upstream node_server {
server localhost:9000;
}
location /auth/ {
proxy_pass http://keycloak_server;
proxy_http_version 1.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;
}
location / {
proxy_pass http://node_server;
proxy_http_version 1.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;
}
Front end server calls a backend api using Angular. REST api calls looks like https://backend.com/callTest
Backend server(running on tomcat) <-> NGINX <-> Spring Boot(with keycloak)
nginx sample
location / {
proxy_pass http://127.0.0.1:8080/dt-1.0/;
proxy_http_version 1.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;
}
in angular keycloak.json looks like
{
"realm": "demo",
"auth-server-url": "https://frontend.com/auth",
"ssl-required": "none",
"resource": "tutorial-frontend",
"public-client": true
}
in spring boot keycloak properties look like
keycloak.auth-server-url=https://frontend.com/auth
keycloak.realm=demo
keycloak.resource=tutorial-frontend
keycloak.public-client=true
keycloak.bearer-only = true
keycloak.cors = true
keycloak.security-constraints[0].authRoles[0]=user
keycloak.security-constraints[0].securityCollections[0].patterns[0]=/*
Please let me know how to correct this. I would really appreciate it.
Three years later, I have encountered the same problem. Maybe you have solved it, but I guess there are still many people who have encountered this problem like me. My solution is to use openresty. You will find many tutorials or code fragments of openresty. I won't talk more about it here.
I just put access_token in the request header after the openresty authentication is passed, just like this
local opts = {
redirect_uri_path = "/redirect_uri",
discovery = "https://a.b.c.d:8093/auth/realms/xxx/.well-known/openid-configuration",
client_id = "client_id",
client_secret = "client_secret",
redirect_uri_scheme = "https",
logout_path = "/logout",
redirect_after_logout_uri = "https://a.b.c.d:8093/auth/realms/xxx/protocol/openid-connect/logout?redirect_uri=https://a.b.c.d:8093/",
scope = "openid email",
access_token_expires_leeway = 0,
accept_none_alg = false,
accept_unsupported_alg = false,
renew_access_token_on_expiry = true,
session_contents = {access_token=true, id_token = true}
}
local res, err = require("resty.openidc").authenticate(opts)
if err then
ngx.status = 403
ngx.say(err)
ngx.exit(ngx.HTTP_FORBIDDEN)
end
ngx.req.set_header("Authorization", "Bearer " .. res.access_token)
In the nginx configuration file, I did this
location /auth/ {
proxy_pass http://keycloak:8080/auth/;
proxy_set_header Host $host:$server_port;
}
location / {
access_by_lua_block {
require("oidc/acc")()
}
try_files $uri $uri/ /index.html;
index index.html;
}
location /api/ {
access_by_lua_block {
require("oidc/acc")()
}
proxy_set_header Host $host:$server_port;
proxy_pass http://gateway:8881/api/;
}
i am trying to configure nginx to proxy pass the request to another server,
only if the $request_body variable matches on a specific regular expression.
My problem now is, that I don't how to configure this behaviour exactly.
I am currently down to this one:
server {
listen 80 default;
server_name test.local;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
if ($request_body ~* ^(.*)\.test) {
proxy_pass http://www.google.de;
}
root /srv/http;
}
}
but the problem here is, that root has always the upperhand.
the proxy won't be passed either way.
any idea on how I could accomplish this?
thanks in advance
try this:
server {
listen 80 default;
server_name test.local;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
if ($request_body ~* ^(.*)\.test) {
proxy_pass http://www.google.de;
break;
}
root /srv/http;
}
}
Nginx routing is based on the location directive which matches on the Request URI. The solution is to temporarily modify this in order to forward the request to different endpoints.
server {
listen 80 default;
server_name test.local;
if ($request_body ~* ^(.*)\.test) {
rewrite ^(.*)$ /istest/$1;
}
location / {
root /srv/http;
}
location /istest/ {
rewrite ^/istest/(.*)$ $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://www.google.de;
}
}
The if condition can only safely be used in Nginx with the rewrite module which it is part of. In this example. The rewrite prefixes the Request URI with istest.
The location blocks give precedence to the closest match. Anything matching /istest/ will go to the second block which uses another rewrite to remove /istest/ from the Request URI before forwarding to the upstream proxy.
I have 2 servers,
with IP xx.xx.xx.xx, situated in Germany ... (running frontend: nginx(static content), backend: Apache2)
with IP yy.yy.yy.yy, situated in Italy...
All requests at the moment is sending to server with IP xx.xx.xx.xx,
How can I proxy all traffic from xx.xx.xx.xx to yy.yy.yy.yy using nginx ...
request proxy, request
Internet -> xx.xx.xx.xx(nginx) -> yy.yy.yy.yy(nginx, Apache)
<- <-
response proxy, response
For others. Answer for subject is configure Nginx like:
server {
listen 80;
server_name mydomain.example;
location / {
access_log off;
proxy_pass http://mydomain.example:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
You can use upsteream like:
upstream xx.xx.xx.xx:8080{
#ip_hash;
server xx.xx.xx.xx:8080 max_fails=2 fail_timeout=2s;
server yy.yy.yy.yy:8181 max_fails=2 fail_timeout=2s;
}
then you can use the cookie or header to set the request like:
location /app {
if ($cookie_proxy_override = "proxy-target-A") {
rewrite . http://xx.xx.xx.xx:8080/app;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
break;
}
if ($cookie_proxy_override = "proxy-target-B") {
rewrite . http://yy.yy.yy.yy:8181/webreg;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
break;
}
proxy_pass http://xx.xx.xx.xx:8080/webreg;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
We have a blog that we host on github with Jekyll; it is there : http://blog.superfeedr.com
Ideally, I want it to be at http://superfeedr.com/blog/ because we need to add some AJAX and we need to avoid the "Same Origin Policy" problems.
We use Nginx on our "main" webserver, and I have the following setup :
location /blog/ {
proxy_pass http://blog.superfeedr.com/;
proxy_redirect off;
proxy_max_temp_file_size 0;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
Unfortunately, as you can see if you go to http://superfeedr.com/blog/ this obviously doesn't work. Oddly enough, we're redirected to Github's homepage.
PS: obviously, we could host the blog on our main server, but the goal is to host it on a different host so that we can almost guarantee it to be online if the site is down...
First, nginx does not send Host header to the blog.superfeedr.com. This makes it send all the required headers:
proxy_set_header Host blog.superfeedr.com;
proxy_set_header X-Host blog.superfeedr.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Second, some url rewriting required. By some weird reason this depends on the version of nginx you are using. Anyway,
for 0.6.x (0.6.32 for me) this should work:
location /blog {
rewrite ^/blog(.*)$ /$1 last;
error_page 402 = #blog;
return 402;
}
location #blog {
proxy_pass http://blog.superfeedr.com;
# the rest of proxying parameters should be here
proxy_set_header Host blog.superfeedr.com;
proxy_set_header X-Host blog.superfeedr.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
You also need to cover all the paths the blog refers to (css, images etc), e.g.
location /css {
error_page 402 = #blog;
return 402;
}
For 0.7.59:
location /blog {
set $blog 1;
rewrite ^/blog(.*)$ /$1 last;
}
location /css {
set $blog 1;
error_page 402 = #blog;
return 402;
}
location / {
if ($blog) {
error_page 402 = #blog;
return 402;
}
# here is where default settings for / should be
root /usr/local/www/nginx/;
}
location #blog {
proxy_pass http://blog.superfeedr.com;
# the rest of proxying parameters should be here
proxy_set_header Host blog.superfeedr.com;
proxy_set_header X-Host blog.superfeedr.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Another way to do this (but without involving nginx) could be with a DNS directive. I think most DNS services offer URL forward service.
For example, in hover.com, first add blog with A directive to 64.99.80.30 under DNS tab, and then in the Forward tab, add blog forward to http://superfeedr.com/blog/
In dnsimple.com, it's simpler, just add blog URL record to forward to http://superfeedr.com/blog/
These forwards, I believe, also work for https:// type URLs.