problem using variable in nginx location directive - nginx

good evening. i have a question regarding nginx and it is related to the location directive. i currently have this configuration in nginx
server {
server_name ~^(?<account>.+)\.domain\.com$;
root /var/www/html/folder-frontend/;
index index.html;
error_log /var/log/nginx/$account-access.log;
access_log /var/log/nginx/$account-access.log;
location / {
try_files $uri /index.html;
}
location /$account-backend/ {
proxy_pass http://service-backend/;
proxy_set_header HOST $account-backend.domain.co;
proxy_http_version 1.1;
}
}
this means that I have several domains with the ending tenant.domain.com(app1.domain.com, app2.domain.com). with the expression (?.+) I am getting part of the string in the url that interests me and then in the location directive use it to make a proxypass and redirect the requests. but this is not working, I know because when I put in the location what interests me (in this case would be location /app1-backend/) if redirects to the backend service that I have listening in another nginx.
My doubt is, can I use a variable in the location directive of nginx? I tried it that way specified and it does not work.

No, you can't use a variable as location directive argument, even in a regex matching ones. You can try a workaround like
server {
server_name ~^(?<account>.+)\.domain\.com$;
root /var/www/html/folder-frontend/;
index index.html;
error_log /var/log/nginx/$account-access.log;
access_log /var/log/nginx/$account-access.log;
location / {
try_files $uri /index.html;
}
location ~ ^/(?<prefix>[^.]+)-backend(?<suffix>/.*) {
if ($prefix != $account) {
return 404;
}
proxy_pass http://service-backend$suffix$is_args$args;
proxy_set_header HOST $prefix-backend.domain.co;
proxy_http_version 1.1;
}
}

Related

nginx allow client_max_body_size for pattern

Im trying to acheive something like:
location /api/ {
proxy_pass http://nest:3500;
include nginxconfig.io/proxy.conf;
if ($request_uri ~* ^/api/(a|b|e) ) {
client_max_body_size 50m;
}
}
but Im getting the error:
"client_max_body_size" directive is not allowed here in /etc/nginx/sites-available/cloud.conf:59
How is that possible within the location /api/ to allow client_max_body_size for specific routes?
Thanks
How is that possible within the location /api/ to allow client_max_body_size for specific routes?
Use 2 location blocks
Other changes may be required, but just use 2 location blocks:
Either nested:
location /api/ {
proxy_pass http://nest:3500;
include nginxconfig.io/proxy.conf;
location ~ ^/api/(a|b|e)/ {
client_max_body_size 50m;
}
}
Or not:
location /api/ {
proxy_pass http://nest:3500;
include nginxconfig.io/proxy.conf;
}
location ~ ^/api/(a|b|e)/ {
client_max_body_size 50m;
proxy_pass http://nest:3500;
include nginxconfig.io/proxy.conf;
}
This allows greater control and avoid using if which is evil and can easily cause a lot of confusion/problems.

Nginx - How to serve a static file to a particular user agent?

I am trying to restrict access to a particular json file for a certain user-agent using the configuration files in Nginx.
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri$args $uri$args/ /index.html;
}
location /v1/ {
proxy_pass http://127.0.0.1:8118;
proxy_pass_header Server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location = /v1/apischema {
root /usr/share/nginx/json;
if ($http_user_agent ~ useragentname) {
try_files /openapi.json;
break;
}
}
}
The idea is to restrict access to openapi.json for an internal user.
Please let me know where I am going wrong.
try_files can be used in a server or location block. See Context: in this document.
There are a number of ways to achieve this.
Using if:
location = /v1/apischema {
if ($http_user_agent ~ useragentname) {
rewrite ^ /openapi.json last;
}
}
location = /openapi.json {
internal;
root /usr/share/nginx/json;
}
The internal directive prevents this URI being accessed directly. See this caution on the use of if.
Or using map with try_files:
map $http_user_agent $apischema {
~useragentname /openapi.json;
default /nonexistant;
}
server {
...
location = /v1/apischema {
root /usr/share/nginx/json;
try_files $apischema =404;
}
}
See this document for details.

Serve both static website & SPA (node.js) with NGINX

I need a way to serve both static html website and SPA using NGINX.
https://website.com -> should be the static index.html page.
https://website.com/register -> should point to SPA powered by node.js webserver.
So, if there's an appropriate static html route it should be served with NGINX, any other route should be served by node.js webserver.
e.g.
https://website.com/about -> served by NGINX because there's about.html
https://website.com/register -> served by node.js because there's no appropriate static page for this route (there's no register.html).
I've created the following configuration, but it doesn't seems to work properly.
upstream backend {
server localhost:8080;
}
server {
listen 80;
server_name website.com www.website.com;
root /var/www/website.com;
location = / {
try_files /index.html =404;
}
location = /index {
return 404;
}
location / {
try_files $uri/index.html =404 #backend;
}
location #backend {
proxy_pass http://backend;
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;
proxy_redirect off;
}
}
Your configuration could probably be simplified to this:
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ #backend;
}
location #backend {
...
}
You could try something like
location / {
try_files $uri $uri.html $uri/ #backend;
}
Breaking it down for you. The try_files directive
Checks the existence of files in the specified order and uses the first found file for request processing;
So
$uri - look for the exact file as defined in the path. Useful for static files like css, images, js, etc..
$uri.html look for the exact file with a .html extension. This would get your about.html
$uri/ - looks for it to be a directory then uses the index directive to look for index or index.html
#backend - send to the proxied application would be responsible for returning 404

nginx proxy_pass to all pages

So I am using nginx to reverse proxy to another server. This wasn't serving static files, until I linked them in the location. The location block is super long, but looks similar to the code below. I'm sure that I'm doing this the wrong way, but it works, it's just tedious to write all the paths. I'm wondering if there's a better way.
location / {
proxy_pass www.example.com;
}
location /sytlesheet.css {
proxy_pass www.example.com/stylesheet.css;
}
location /page1 {
proxy_pass www.example.com/page1;
}
#this goes on and on
Is there a way to get everything past the '/' for example 'page1', and pass that to the proxy without manually typing it?
I'm hoping there's something a way to use a variable or something to link all the pages and resources with a single location block:
location / {
proxy_pass www.example.com;
}
location /$variable {
proxy_pass www.example.com/$variable;
}
Thanks!
You should use following code
location / {
# First attempt to serve request as file, then
# as directory, then fall back to proxy
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_pass www.example.com;
}
Check this out.
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://www.example.com;
}

Serving a.html from apache while requesting b.html

I'm creating a nginx reverse proxy to apache. Apache runs on port 8080 and nginx on 80.
I hope to achieve the following;
When I request the page http://server/test.html it should be proxyed to http://server:8080/unknown.html
Later on I'll do some eval stuff on the pages and redirect the users to the right pages, but I can't even get this to work. I get the test.html back as response all the time.
My nginx config:
server {
listen 80;
root /var/www/;
index index.php index.html index.htm;
server_name example.com;
location / {
# try_files $uri $uri/ /index.php;
}
location ~ \.html$ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
#rewrite ^/unknown.html;
proxy_pass http://127.0.0.1:8080;
proxy_redirect http://127.0.0.1/test.html http://127.0.0.1:8080/unknown.html;
}
location ~ /\.ht {
deny all;
}
}
I have zero experience yet, but I'm eager to learn how to get this working...
Firstly, the proxy_redirect directive is the opposite of what you need. It is only used to rewrite the Location response headers in 3xx responses from upstream. See this document for details.
You can use a rewrite ... break statement within the location block that performs the proxy_pass, for example:
location ... {
rewrite ^/test.html$ /unknown.html break;
proxy_pass ...;
}
See this document for details.

Resources