We have a handful of homogenous application loosely under SOA pattern. Because of homogeneity, we have been able to define some neat pattern in Nginx to proxy all of our SOA apps through one configuration. Following Nginx configuration is absolutely working absolute wonders in conjunction with DNSmasq to resolve anything.yourdomain.devel eg. a.stackoverflow.devel, b.stackoverflow.devel domains and route that to appropriate app servers under your project folder via designated ports via maps.
worker_processes 2;
events {
worker_connections 1024;
}
http {
map $host $static_content_root {
hostnames;
default /path/to/project/folder;
# For typical standalone apps living in your project directory
# *.myapp.local.devel -> /path/to/project/myapp/public
~^([^\.]+\.)*(?<app>[^\.]+)\.devel$ /path/to/project/folder/$app/public; #rails pattern
}
map $app $devel_proxy_port1 {
default 3000;
domain1 3000;
domain2 4000;
}
map $app $devel_proxy_port2 {
default 3001;
domain1 3001;
domain2 4001;
}
server {
listen 127.0.0.1;
server_name ~^([^\.]+\.)*(?<app>[^\.]+)\.[^\.]+.devel$;
location / {
root $static_content_root; # Using the map we defined earlier
try_files $uri $uri/index.html #dynamic;
}
location #dynamic {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forward-Proto http;
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
proxy_pass http://127.0.0.1:$devel_proxy_port1;
}
}
}
Now, in order to simulate multiple servers behind Nginx load balancer. I thought of doing following proxy configuration which points to upstream rather than directly pointing to one server:port pair.
proxy_pass http://backend;
upstream backend {
server http://127.0.0.1:$devel_proxy_port1;
server http://127.0.0.1:$devel_proxy_port2;
}
I thought above would work but it always emits following error hinting the variables of map blocks are not available inside upstream context.
[emerg] 69478#0: invalid host in upstream "http://127.0.0.1:$devel_proxy_port1" in /usr/local/etc/nginx/nginx.conf:57
Is this an expected behavior?
Yes, variable can not be used inside upstream. You can create few upstream blocks with different names (upstream backend, upstream backend_domain, etc), resolve upstream name through map and put this variable to proxy_pass:
upstream backend {
server http://127.0.0.1:3000;
server http://127.0.0.1:3001;
}
upstream backend_domain1 {
server http://127.0.0.1:3002;
server http://127.0.0.1:3003;
}
upstream backend_domain2 {
server http://127.0.0.1:3004;
server http://127.0.0.1:3005;
}
...
upstream backend_domain30 {
server http://127.0.0.1:3060;
server http://127.0.0.1:3061;
}
map $app $devel_proxy {
default backend;
domain1 backend_domain1;
domain2 backend_domain2;
...
domain30 backend_domain30;
}
...
proxy_pass $devel_proxy;
...
In some cases you can skip map block using $app inside proxy_pass: proxy_pass backend_$app;, but need additional checks for $app values. Also, map allow to to map different "domains" to same applications.
Related
I'm trying to configure nginx to serve both frontend and backend routing. All is done with use of docker. Here's my nginx config:
upstream client {
server client:3000;
}
upstream api {
server api:3001;
}
server {
listen 80;
location / {
proxy_pass http://client;
}
location /sockjs-node {
proxy_pass http://client;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /auth/ {
rewrite /auth/(.*) /$1 break;
proxy_pass http://api;
}
}
The thing is that when I'm using in my front requests routes beginning with /apiit rewrites it but without /api part persisted, so it is looking for /. How can I work it that to persist /api part?
I have multiple backend servers and I want to proxy all servers using a single nginx server instance. I don't want to change nginx.conf whenever I add a new backend server.
For example: Server 1 : 192.168.10.1:8080, Server2: 192.168.10.2:8080, etc
Nginx is running on example.com. I want to access Server1 by using example.com?ip=192.168.10.1, example.com?ip=192.168.10.2 etc
I tried this configuration, but it is giving 500 error page.
location / {
proxy_pass http://$arg_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Is there something I am missing? Is there any other way of achieving this?
server {
server_name dynamic_host;
listern 8080;
#resolver 8.8.8.8;
#seems you don't need resolver because you use ip address
location / {
if ( $arg_address != "" ) {
proxy_pass $arg_address;
#proxy_pass $arg_address$uri
#proxy_pass $arg_address$request_uri
}
}
}
the difference between the three proxy_pass
$proxy_address
example.com?address=http://192.168.10.2:8080/ goes to
http://192.168.10.2:8080/
$proxy_address$uri
example.com/test/path?address=http://192.168.10.2:8080/ goes to
http://192.168.10.2:8080/test/path
$proxy_address$request_uri
example.com/test/path?address=http://192.168.10.2:8080/¶m=value goes to
http://192.168.10.2:8080/test/path?address=http://192.168.10.2:8080/¶m=value
you can change the param address to ip, in this case, don't forget to change $arg_address to $arg_ip.
reference:
http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
I'm using a variable to define my proxy_pass target, similar to this answer except in my case the value is extracted from a query param on the incoming request, so e.g. /?url=http://example.com will be proxied to example.com. Since the proxy_pass argument is a variable, I have no upstream directive in my config. The proxying works fine. However, the connection is closed after each request and I want to them alive to amortize the TCP handshake. According to these directions, that requires a keepalive directive in the upstream directive. How can I do this without an upstream directive?
Here's my full config:
server {
if ($arg_url ~ \/\/([^\/]*)) {
set $proxy_host $1;
}
if ($proxy_host = "") {
return 404;
}
resolver 8.8.8.8;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $proxy_host;
proxy_pass $arg_url;
}
}
I'm trying to reverse proxy an api with Nginx. I have the following configuration:
worker_processes 4;
events { worker_connections 1024; }
http {
upstream some_upstream {
server 1.something.com;
server 2.something.com;
}
server {
listen 80;
location ~/proxyNow/(?<zvar>(\w+))/(?<xvar>(\w+))/(?<yvar>(\w+))/ {
proxy_pass http://some_upstream/hello/something/$zvar/$xvar/$yvar/somethingelese;
proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache maps_cache;
proxy_cache_valid 200 302 365d;
proxy_cache_valid 404 1m;
proxy_redirect off;
}
}
}
When I try to call the following url http://localhost:82/proxyNow/1/2/3/?app_id=someAppId&app_code=someCode
I get the following error message:
Invalid URL
The requested URL
"http://%5bNo%20Host%5d/hello/something/1/2/3/somethingelese", is
invalid. Reference #9.be35dd58.1489086561.5c9bd3c
It seems that the host cannot be retrieved by nginx. But if I execute the call directly:
http://1.something.com/hello/something/$zvar/$xvar/$yvar/somethingelese?app_id=someAppId&app_code=someCode
http://2.something.com/hello/something/$zvar/$xvar/$yvar/somethingelese?app_id=someAppId&app_code=someCode
It seems that Nginx for some reason is not able to resolve the host
You should take a look into the doc.
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
When location is specified using a regular expression.
In this case, the directive should be specified without a URI.
I suggest the following solution without expensive regex location.
http://nginx.org/en/docs/http/ngx_http_core_module.html#location
location /proxyNow/ {
rewrite /proxyNow/(?<zvar>(\w+))/(?<xvar>(\w+))/(?<yvar>(\w+))/.* /hello/something/$zvar/$xvar/$yvar/somethingelese$is_args?$args break;
proxy_pass http://some_upstream;
... other nginx diretives;
}
Suddenly my nginx configuration stopped working.
events {}
http {
upstream node-app {
server qa:3000;
}
server {
listen 8080;
server_name name.com;
location / {
proxy_pass http://node-app;
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;
}
}
server {
listen 80;
server_name name.com;
root /var/www/name.com/webapp;
auth_basic "Password required";
auth_basic_user_file /etc/nginx/.htpasswd;
location ~ \.css {
include /etc/nginx/mime.types; # css files wont be loaded if mime type wont be text/css
}
}
}
Nothing gets logged/works for connections to port 8080. I have tested if it is caused by the proxy by removing location block and instead using configuration from server at port 80 configuration, it is still not working.
I am using docker-compose to setup nginx and server listening at port 3000. Nothing has changed in the docker configuration since last time things were working.
Any help is welcome.