how to specify nginx nested location in another directory - nginx

I have a config that looks like:
server {
listen 80;
root /pubStuff;
...stuff...
location /something {
root /app/something
}
}
The intention is, that while I can access stuff in the door of the server using example.com/ or with whatever directory/files location in /pubStuff, IF someone were to request example.com/something, or example.com/something/something.here.zip, they would get it!
When I try to go for example.com/something, I get a 404 not found error!
In error log it says:
14#14: *15409 open() "/app/something/something" failed (2: no such file or directory)....
I dont understand why does it affix a second "something", when I asked for only example.com/something, which should show me the content of /app/something as configured above, right?
I read the documentation on http://nginx.org/en/docs/http/ngx_http_core_module.html#location but it is rather focused on the prefix matching stuff, not explaining whats wrong in my use case.
Based on stackoverflow suggestions, I tried the solution at Nginx -- static file serving confusion with root & alias
basically, it seems that only should only specify root /app/, and that it would go to /app/something/something.zip, but error log says it tries /pubStuff/something/something.zip, totally ignoring the root directive for /something.

Related

Can't send auditlog with modsecurity with custom error pages

I'm using Modsecurity v3.0.3 with the blocking module and I need to get my auditlog.
Also, because I need it, I have to use some custom error pages.
Unfortunately, I have my logs, but I'm losing my auditlog.
I tried some forums' help, but it didn't work for me.
One of the forums : https://github.com/SpiderLabs/ModSecurity-nginx/issues/76
Here is the location configuration of my NGinx
Any help or starting point would be appreciated, thanks !
I had the same problem with ModSecurity 3.3.2 + nginx and custom errors, so leaving this here in case other people run into the same issue as it took me a while to find a solution.
The issue in my case was that I had the custom error in nginx return the message directly in the error location block, so something like:
error_page 400 #error400;
location #error_400 {
types {}
default_type application/json;
return 400 '{"message: WHATEVER ERROR"}'
}
So the solution in my case was to put that exact JSON message in a file and reference that file instead, so the above becomes:
error_page 400 /400.json;
location = /400.json {
types {}
default_type application/json;
root /usr/share/nginx/html/custom_errors/;
}
And in that root path I put the 400.json file with that exact error messsage:
cat /usr/share/nginx/html/custom_errors/400.json
{"message: WHATEVER ERROR"}
This brought back the SecAudit Logs from ModSecurity. Hope this helps someone.
Could you elaborate on "losing my auditlog"? This sounds as if you would see it for a moment, but then it disappears.
Also, you link to a very old ModSec issue that has been fixed and released in the meantime. Where is the connection?

Can't get nginx to match part of the path

I have nginx running as in a docker-compose setup and I want to achieve to following:
Every url that contains /something/ is passed to application 1
Every url that contains /something/alsothis/ is passed to application 2
My current config has:
location ~* ^/something/(?<path>.+) {
proxy_pass http://app1/$path;
}
location ~* ^/something/alsothis/(?<path>.+) {
proxy_pass http://app2/$path;
}
When I try https://www.example.com/something/rest_of_path it is working fine.
However when I try https://www.example.com/something/alsothis/rest_of_path I get an Unkown error in Postman (500 error is logged in nginx).
Also I double checked that app2 is working. When I change to the first location to app2, it also works fine.
Can't seem to figure out what is going wrong, all help is much appreciated.
Thanks in advance!
Richard was right, just had to change the order.

Running Nginx and Drupal

I am new to Nginx but I managed to install Drupal on windows 8 machine. I just noticed that this URL(http://localhost:8080/drupal/) spits out error message 403 Forbidden. If I mutate that URL a bit by including the index(http://localhost:8080/drupal/index.php) file then it works as expected. My question is this:
How could I configure Nginx so that I wont get error message when I go to http://localhost:8080/drupal/?
Depending on your configuration, an index directive will encourage nginx to look for specific files when encountering a directory:
index index.php;
For a more specific rule, to single out that one path and map it to the controller, you could use an exact match location directive:
location = /drupal/ { rewrite ^ /drupal/index.php last; }
See this and this for more.

conditional rewrite or try_files with NGINX?

I'm having trouble setting up a conditional rewrite, and I've been trying to use the if directive (despite all sources indicating it's "evil") with the -f switch to check for the presence of a file, but it's not working. I believe the issue/case is best explained by example, so here goes:
Directory structure
workspace/
myapp/
webroot/
index.php
assets/
baz.js
hello/
foo.js
modules/
hello/
assets/
foo.js
bar.js
Expected results
/ => /workspace/myapp/webroot/index.php
/assets/hello/foo.js => /workspace/myapp/webroot/assets/hello/foo.js
/assets/hello/bar.js => /workspace/myapp/modules/hello/assets/foo.js
/assets/baz.js => /workspace/myapp/webroot/assets/baz.js
In summary:
foo.js is only present in the modules/hello/assets folder and gets delivered from there.
bar.js is present both in webroot/assets/hello and modules/hello/assets and gets delivered from webroot.
(it hides/overrides the file in modules)
baz.js is only present in webroot/assets and gets delivered from there.
The part that doesn't work right now, is this:
location /assets/ {
if (-f $uri) {
break;
}
root /workspace/myapp/modules;
rewrite ^/assets/([^/]+)/(.*)$ /$1/assets/$2 break;
}
Namely the if directive, doesn't seem to have any affect - the bar.js file gets delivered from modules rather than webroot.
Should I be using if or not?
Is there any way I can solve this problem with try_files instead? I can't seem to grasp how this would work together with rewrite which I can't seem to get around.
Please do not suggest reorganizing the assets using a deploy script or something - it's not an option, for various other reasons.
I have used this pattern with Apache before, and NGINX seems more capable in most respects, so I'm sure this must be possible?
One requirement that isn't absolute, is I don't have to be able to override modules/hello/assets/foo.js with webroot/assets/hello/foo.js - serving scripts from webroot/assets/* is however a requirement.
The answer is divided into two parts: the first part explains why your configuration does not work and the second one provides examples of how to solve your problem. If you are only interested in the solution, go straight to the second part.
The problem
First of all, note that the positon of the root directive in a location block is not important. It does not matter if you put it at the very top or at the bottom of a location, it will affect the whole location anyway. Also, keep in mind that break in the end of the rewrite line tells Nginx to stay within the current location even if the URI has been successfully rewrited.
Having said that, let's take a look at your configuration and see how every request from the Expected results is processed and why nothing works as expected.
Let's presume that there is no other suitable location with a higher priority in your configuration. Since every request from Expected results starts with /assets, all of them will be handled according to the rules presented in your location. So:
/assets/hello/foo.js
The root is set to /workspace/myapp/modules. The if directive will be evaluated to false, because /assets/hello/foo.js does not exist and so break will not be executed. Finally, the last rewrite will change the requested URI from /assets/hello/foo.js to /hello/assets/foo.js and the following break will tell Nginx to stay within the current location. As a consequence /workspace/myapp/modules/hello/assets/foo.js will be served.
/assets/hello/bar.js
This request is processed exactly the same way as the previous one, so /workspace/myapp/modules/hello/assets/bar.js will be served.
/assets/baz.js
Yet again the root is set to /workspace/myapp/modules and the if is evaluated to false. But this time the final rewrite will not change the URI, because the request does not match the regular expression. As a consequence Nginx will try to serve /workspace/myapp/modules/assets/baz.js and since there is no such file exists, will return 404.
As you can see your configuration cannot possibly work as you want it to for several reasons:
if is always evaluated to false, because you try to check URIs and not files;
the request stays within the location because you tell it to stay there with break in the rewrite line;
root is always set to /workspace/myapp/modules in this location so no file can be served from anywhere else.
The solutions
The easiest solution would be to use try_files:
root /workspace/myapp/webroot;
location /assets/ {
try_files $uri #modules;
}
location #modules {
root /workspace/myapp/modules;
rewrite ^/assets/([^/]+)/(.*)$ /$1/assets/$2 break;
}
This configuration tells Nginx to look for a file in the webroot folder first and if nothing is found then go to the modules folder in another location. This approach is considered most preferable.
On the other hand, using if would allow you to solve the problem within one location:
location /assets/ {
root /workspace/myapp; # The parent folder
if (-f $document_root/webroot/$uri) {
rewrite ^(.*)$ /webroot/$1 break;
}
rewrite ^/assets/([^/]+)/(.*)$ /modules/$1/assets/$2 break;
}
However, this approach is considered outdated is not recommended for use.

run cgi script using nginx

I am trying to execute cgi script on Nginx. In nginx.conf file, I added a location directive such as below:
location /cgi-bin{
root cgi-bin;
index index.cgi;
}
When I try to connect to http://example.com/cgi-bin/index.cgi, it says file not found. In error.log, I see the request as "http://example.com/html/cgi-bin/index.cgi.
cgi-bin is not in html folder. The correct path is "http://example.com/cgi-bin/index.cgi
I tried many possibilities for location directive. Either it looks in html/cgi-bin or it does /cgi-bin/cgi-bin/index.cgi. I am not sure why it uses 'cgi-bin' twice
Any suggestions.. I have been trying for hours now!!!

Resources