Nginx multiple locations each with its own root - nginx

server {
listen 80;
server_name ~^(?<cc>.+?).local.solar.bc.digital$;
client_max_body_size 1m;
root /home/vagrant/sites/$cc/_www/;
index index.html index.htm index.php;
error_page 404 /index.php;
access_log /var/log/nginx/$cc-access.log;
error_log /var/log/nginx/$cc-error.log;
charset utf-8;
sendfile off;
location / {
root /home/vagrant/sites/$cc/_www/php/;
try_files $uri $uri/ /index.php?$query_string;
}
location /shop/ {
# root /home/vagrant/sites/$cc/_www/bcshop/;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param APP_ENV dev;
fastcgi_param PLATFORM_ENVIRONMENT local;
fastcgi_read_timeout 300;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
}
location ~ /\.ht {
deny all;
}
}
Right, given the config above. If you see what I am trying to do, know that it's not working!
Some details:
I have the general 'root', because without I get errors.
This is on a local VM used for development. We have a deployment tool locally that for each project (refer to $cc variable in the config above), it can deploy up to two apps. Not necessarily both are deployed for each project. The first app is deployed in /home/vagrant/sites/$cc/_www/php, the second one in /home/vagrant/sites/$cc/_www/bcshop (but I can make it shop - you'll see why from the config)
Both apps run on Drupal, so the way the load is the same. I simply can't make them work. I get file not found for both with most of the small variants I've tried.
When I place the second app in /home/vagrant/sites/$cc/_www/shop (rather than /home/vagrant/sites/$cc/_www/bcshop) I can get its homepage to load, but nothing else.
When I disregard the second app, and concentrate on the first, I can simply have a general root set to /home/vagrant/sites/$cc/_www/php and remove the local root from location /. That works. But it doesn't when it's specified as local root. In this case, in fact, I get this error in the logs: "FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream". This only for the first app.
If you wonder why the general root is set to that value, it's because I get an error in the logs if the general root is not verifiable for the location being matched. Makes sense?
I think I've covered pretty much all of what I've done in summary.
Thoughts?
I am not an expert at all with nginx, so I am going by trial and errors, with the help of the docs and other questions answered on here. But so far, no joy.
Thanks all.

You have PHP files in both the _www/bcshop/ path and the _www/php/ path. If you would like to use one common location ~ \.php$ for both applications, then the URI for each application will need to be prefixed by /bcshop and /php respectively. That is, both applications appear to run in a subdirectory.
I suspect that you would like to use /shop prefix for one application, and the / prefix for the other. in which case two location ~ \.php$ blocks will be required.
One application runs from the server root:
root /home/vagrant/sites/$cc/_www/php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $request_filename;
...
}
And one application runs with a URI prefix of /shop but located in the subdirectory _www/bcshop:
location ^~ /shop {
rewrite ^/shop(?:/(.*))?$ /bcshop/$1 last;
}
location ^~ /bcshop/ {
internal;
root /home/vagrant/sites/$cc/_www;
try_files $uri /shop/index.php?$query_string;
location ~ \.php$ {
try_files $uri /shop/index.php;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $request_filename;
...
}
}
The ^~ modifier ensures that the location block takes precedence over the regular expression location block above. See this document for details.
Although the external URI prefix is /shop, it is silently rewritten to /bcshop so that we can continue to use the root directive. There is an alias directive, but it has issues with try_files and is tricky to use with PHP.

Based on the answer by #RichardSmith, I come up with my own variant (which is working fine). Simply because repeating the block for location ~ \.php$ was doing my head in.
...
...
root /home/vagrant/sites/$cc/_www/;
...
...
location / {
set $actual_root /home/vagrant/sites/$cc/_www/php/;
set $fastcgi_index /index.php;
root $actual_root;
try_files $uri $uri/ $fastcgi_index?$query_string;
}
location /shop/ {
set $actual_root /home/vagrant/sites/$cc/_www/;
set $fastcgi_index /shop/index.php;
root $actual_root;
try_files $uri $uri/ $fastcgi_index?$query_string;
}
location ~ \.php$ {
root $actual_root;
fastcgi_index $fastcgi_index;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $actual_root/$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param APP_ENV dev;
fastcgi_param PLATFORM_ENVIRONMENT local;
fastcgi_read_timeout 300;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
}
...
...

Related

NGINX location giving 404 error, even though the directory exists [duplicate]

lets say I've a path like:
/var/www/myside/
that path contains two folders... let's say
/static and /manage
I'd like to configure nginx to have an access to:
/static folder on / (eg. http://example.org/)
this folder has some .html files.
/manage folder on /manage (eg. http://example.org/manage) in this case this folder contains Slim's PHP framework code - that means the index.php file is in public subfolder (eg. /var/www/mysite/manage/public/index.php)
I've tried a lot of combinations such as
server {
listen 80;
server_name example.org;
error_log /usr/local/etc/nginx/logs/mysite/error.log;
access_log /usr/local/etc/nginx/logs/mysite/access.log;
root /var/www/mysite;
location /manage {
root $uri/manage/public;
try_files $uri /index.php$is_args$args;
}
location / {
root $uri/static/;
index index.html;
}
location ~ \.php {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
}
}
The / works correctly anyway manage doesn't. Am I doing something wrong? Does anybody know what should I change?
Matthew.
To access a path like /var/www/mysite/manage/public with a URI like /manage, you will need to use alias rather than root. See this document for details.
I am assuming that you need to run PHP from both roots, in which case you will need two location ~ \.php blocks, see example below. If you have no PHP within /var/www/mysite/static, you can delete the unused location block.
For example:
server {
listen 80;
server_name example.org;
error_log /usr/local/etc/nginx/logs/mysite/error.log;
access_log /usr/local/etc/nginx/logs/mysite/access.log;
root /var/www/mysite/static;
index index.html;
location / {
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
location ^~ /manage {
alias /var/www/mysite/manage/public;
index index.php;
if (!-e $request_filename) { rewrite ^ /manage/index.php last; }
location ~ \.php$ {
if (!-f $request_filename) { return 404; }
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}
}
}
The ^~ modifier causes the prefix location to take precedence over regular expression locations at the same level. See this document for details.
The alias and try_files directives are not together due to this long standing bug.
Be aware of this caution in the use of the if directive.

Nginx Laravel and phpmyadmin configuration [duplicate]

So here's my server block
server {
listen 80;
server_name domain.tld;
root /var/www/domain.tld/html;
index index.php index.html index.htm;
location / {
}
location /phpmyadmin {
alias /var/www/phpmyadmin;
}
location /nginx_status {
stub_status on;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
browsing http://domain.tld/index.php works fine the only problem im encountering is browsing http://domain.tld/phpmyadmin/. It returns 404 yet the folder /var/www/phpmyadmin exist on the server. Viewing /var/log/nginx/error.log, no error is being logged there yet the access to it is logged in /var/log/nginx/access.log. What could be the problem here?
The problem is that phpmyadmin is a PHP application and your location ~ \.php$ block does not point to the correct document root.
You need to construct two PHP locations with different document roots.
If phpmyadmin is located at /var/www/phpmyadmin, you do not need an alias directive, as a root directive will be more efficient. See this document.
server {
listen 80;
server_name domain.tld;
root /var/www/domain.tld/html;
index index.php index.html index.htm;
location / {
}
location /nginx_status {
stub_status on;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ^~ /phpmyadmin {
root /var/www;
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
The location ^~ /phpmyadmin is a prefix location that takes precedence over the regex location normally used to process .php files. It contains a location ~ \.php$ block which inherits a value of /var/www for the document root.
It is advisable to include fastcgi_params before defining other fastcgi_param parameters otherwise your custom values may be silently overwritten.
See this document for more.

Working with alias inside location

So here's my server block
server {
listen 80;
server_name domain.tld;
root /var/www/domain.tld/html;
index index.php index.html index.htm;
location / {
}
location /phpmyadmin {
alias /var/www/phpmyadmin;
}
location /nginx_status {
stub_status on;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
browsing http://domain.tld/index.php works fine the only problem im encountering is browsing http://domain.tld/phpmyadmin/. It returns 404 yet the folder /var/www/phpmyadmin exist on the server. Viewing /var/log/nginx/error.log, no error is being logged there yet the access to it is logged in /var/log/nginx/access.log. What could be the problem here?
The problem is that phpmyadmin is a PHP application and your location ~ \.php$ block does not point to the correct document root.
You need to construct two PHP locations with different document roots.
If phpmyadmin is located at /var/www/phpmyadmin, you do not need an alias directive, as a root directive will be more efficient. See this document.
server {
listen 80;
server_name domain.tld;
root /var/www/domain.tld/html;
index index.php index.html index.htm;
location / {
}
location /nginx_status {
stub_status on;
access_log off;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ^~ /phpmyadmin {
root /var/www;
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
The location ^~ /phpmyadmin is a prefix location that takes precedence over the regex location normally used to process .php files. It contains a location ~ \.php$ block which inherits a value of /var/www for the document root.
It is advisable to include fastcgi_params before defining other fastcgi_param parameters otherwise your custom values may be silently overwritten.
See this document for more.

Nginx - Use different directory for serving files while stripping out path from URL

I am trying to use different directory from where to serve the files, but have been unsuccessful. /var/www/site.app/public is where the root, but I want to serve news from /var/www/news/api instead, while having URL http://site.app/news/123, from which I want to remove the news part, because otherwise it would map to /var/www/news/api/news/123.
Judging by the debug logs, it seems that it gets rewritten correctly when first testing all location blocks, but after it is done rewritting, it goes through all of them again, and ends up serving content with location block /.
Here is my configuration file I have.
server {
listen 80;
server_name site.app;
root /var/www/site.app/public;
rewrite_log on;
error_log /var/log/nginx/error.log debug;
index index.php index.html;
location / {
try_files $uri $uri/ index.php?$query_string;
}
location /news/ {
root /var/www/news/api;
rewrite ^/news/(.*) /api.php?_=$1;
index index.php index.html;
}
location ~ \.(hh|php)$ {
try_files $uri /index.php =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The root directive in your /news/ location currently does nothing. You are rewriting the URI to /api.php which then hits your \.(hh|php)$ location, which inherits the root from the parent server container.
You need a distinct location for /api.php, possibly /news/api.php. In which case you can construct a separate location block (possibly nested within /news/) where you can place fastcgi_pass code using the different root.
So this is not ideal solution, but it works. By default it would still allow access to api.php, but I am denying access to it by checking if the URL contains /news/
server {
listen 80;
server_name site.app;
root /var/www/site.app/public;
index index.php index.html;
location / {
try_files $uri $uri/ index.php?$query_string;
}
location = /api.php {
if ($request_uri !~ ^/news/) {
return 444;
}
root /var/www/site.app/news/;
try_files $uri $uri/ /api.php?$query_string =408;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /news/ {
rewrite ^/news/(.*) /api.php?$1;
}
location ~ \.(hh|php)$ {
try_files $uri /index.php =407;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

NGINX sef urls error: No input file specified

I've been struggling with a NGINX configuration. I've set up a development environment (local laptop) with a configuration supporting search engine friendly (SEF) urls, but the same configuration doesn't seem to work on my test server.
local configuration:
server {
server_name example;
root /home/arciitek/git/example/public;
client_max_body_size 500M;
location /collection/ {
try_files $uri $uri/ /collection/index.php$args;
index index.php;
}
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/arciitek/git/example/public/$fastcgi_script_name;
}
}
This works fine. Now on the test environment it looks like this:
{
server_name dev.example.com;
access_log /srv/www/dev.example.com/access.log;
error_log /srv/www/dev.example.com/error.log debug;
root /srv/www/dev.example.com/public;
location /collection/ {
try_files $uri $uri/ /collection/index.php$args;
index index.php;
}
location / {
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/php-fastcgi/php-fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /srv/www/dev.example.com/public$fastcgi_script_name;
}
}
On my development environment everything is fine. But on my test environment, when I call a url in my browser with prettyness added : collection/[brand]/[product]. I get the: No input file specified error. Mind you, if I call a url anding with collection/ everyting works as well..
Can anyone help me with this please? if more info is needed, please let me know..
kind regards,
Erik
After frustrating for a long time, I noticed that it was not the configuration that gave me trouble, but the link to sites-enabled...
There you go... *pads himself on the back...

Resources