nginx allow client_max_body_size for pattern - nginx

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.

Related

problem using variable in nginx location directive

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;
}
}

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.

Different configuration of uwsg_cache depends on url path

I have uwsgi cache configured, but I want to make it work differently for different locations. My config:
uwsgi_cache_path /tmp/nginx_cache/ levels=1:2 keys_zone=mycache:60m inactive=10m;
server {
listen *:80;
server_name thewebsite.loc;
location #uwsgi {
include uwsgi_params;
uwsgi_cache mycache;
uwsgi_cache_valid any 1h;
uwsgi_cache_key $request_uri;
uwsgi_pass unix:///var/run/app/uwsgi.sock;
uwsgi_read_timeout 120s;
}
location / {
try_files $uri #uwsgi;
}
}
let's say, I want to disable cache for a particular location. I add after block for location / another location:
location /dynamic{
uwsgi_cache off;
try_files $uri #uwsgi;
}
But it doesn't work and the view still cached. Is it possible or not supposed to work like this at all?
UPD: I've also tried to configure cache in location /. In this case, it simply doesn't work.
When you access /dynamic the nginx sets uwsgi_cache off but then you redirect to #uwsgi location where you have cache enabled. I think that causes your problem.
Try moving cache config to server context:
uwsgi_cache_path /tmp/nginx_cache/ levels=1:2 keys_zone=mycache:60m inactive=10m;
server {
listen *:80;
server_name thewebsite.loc;
uwsgi_cache mycache;
uwsgi_cache_valid any 1h;
uwsgi_cache_key $request_uri;
location #uwsgi {
include uwsgi_params;
uwsgi_pass unix:///var/run/app/uwsgi.sock;
uwsgi_read_timeout 120s;
}
location / {
try_files $uri #uwsgi;
}
location /dynamic {
uwsgi_cache off;
try_files $uri #uwsgi;
}
}
CAUTION: I did not test this config, I'm not sure if it will work

Is is possible to define a single nginx location in two separate blocks?

Is is possible to define a single nginx location in two separate blocks?
For example:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
# What do I need to do to get this second root location
# to append to the 1st? If it's even possible.
location / {
proxy_pass http://foo;
}
}
The idea is that the root location then effectively becomes:
location / {
proxy_cache off;
proxy_pass http://foo;
}
If you'd like to know more about the why, read on.
Background:
I'm running a GitLab Omnibus installation. According to the docs, an admin an inject custom nginx config to the GitLab server block.
However, this injection adds things to the end server block rather than a specific location block.
So if I try to inject include my_config.conf;, I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
include my_config.conf;
}
and if I try to include location ^~ / {\n include my_config.conf;\n }\n I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
location ^~ / {
include my_config.conf;
}
}
which then causes the nginx config to fail with a duplicate location "/" in /var/opt/gitlab/nginx/conf/gitlab-http.conf:106 error.
Note: my_config.conf contains add_header stuff for CORS, so it needs to be in a location block.
You probably need to understand how nginx processes a request. But location blocks are not additive and must be individually complete. You can place certain statements in the server block and allow individual location blocks to override as required (e.g. proxy_cache).
Assuming that all of your URIs are proxied, you could use something like this:
proxy_cache off;
location / {
proxy_pass http://foo;
}
location /assets {
proxy_cache mycache;
proxy_pass http://foo;
}
Common statements can be offloaded to an include file.

Nginx: cache only specific urls and named location

I have rails application. There are parts of nginx config of it:
upstream app_server {
server unix:/var/www/app/shared/unicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name app hostname;
keepalive_timeout 5;
root /var/www/app/current/public;
try_files $uri/index.html $uri.html $uri #app;
location #app {
proxy_pass http://app_server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_cache off;
}
location ~ /assets/*\.(png|gif|jpg|jpeg|css|js|swf|ico|gz)(\?[0-9]+)?$ {
access_log off;
}
}
I want to cache several pages of my apps (for example all *.json urls). How I can do that?
According to nginx docs I can't:
use nested location in named location
use proxy_cache in if block
You can get away with adding Json to the extensions in the static file block if they are not virtual URLs.
If they are, you need to either setup differently by forwarding everything to your app by default and making exceptions, so you avoid having to use named locations. Or you can set variables based on if statements inside the named location:
location #app {
set $proxy_cache_cfg "off";
if($request_uri ~ \.json$) {
set $proxy_cache_cfg "json_zone";
}
}
Untested, not sure if "off" should be quoted and whether it even would work here. If this won't work, you can always use the reverse approach and set proxy_no_cache based on a variable, since that is in effect for anything non-empty and non-zero.

Resources