Reputation: 2234
I am trying to move an app from apache server to nginx. The problem is that there are multiple apps in subdirectories and I can't find a proper way to configure the server.
What I need:
www.example.com
serves from /srv/app
www.example.com/sub1
serves from /srv/app/sub1
www.example.com/sub2
serves from /srv/app/sub2
Each of the apps need the same config, so I extracted that in a snippet:
# snippets/app.conf
index index.php index.html index.htm index.nginx-debian.html;
location /system {
return 403;
}
# [a couple of other 403s excluded]
# Pass non-file URI to index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# Use PHP
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
# Hide .htaccess
location ~ /\.ht {
deny all;
}
And in the main server file:
# [non-www and http redirects]
server {
# [listen directives]
server_name www.example.com;
root /srv/app;
include snippets/app.conf;
location /sub1 {
root /srv/app/sub1;
include snippets/app.conf;
}
# [other sub-apps included in the same way]
# [ssl stuff]
}
However, this gives me an error:
nginx: [emerg] location "/system" is outside location "/sub1" in /etc/nginx/snippets/app.conf:5
It's obvious from the error that /system
is interpreted as being "absolute" www.example.com/system
instead of the nested www.example.com/sub1/system
. Can I somehow specify that I want the nested locations to be considered relative? Or I just have to repeat the whole near-identical config for every sub-app changing the prefixes?
Upvotes: 0
Views: 1376
Reputation: 2234
It turns out that most of the repeating is not necessary in nginx.
The directives to use fastcgi for .php
and hide /.ht
files were already regexes so they affect everything. It's enough to specify index
once and the default there stuff was redundant if I only want to use index.php
.
As all the apps are nested on the filesystem in the same way as on web, specifying root was not necessary either.
What surprised me was that location ^~ /(system|data)/ { ... }
matches not only www.example.com/system/
, but also www.example.com/sub1/system/
. I thought that ^~
should match only if the location start matches the regex...
# [non-www and http redirects]
server {
# [listen directives]
server_name www.example.com;
root /srv/app;
index index.php;
location ^~ /(system|data)/ {
return 403;
}
# Use PHP
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
# Pass non-file URI to index.php for all locations
location /sub1/ {
try_files $uri $uri/ /sub1/index.php?$query_string;
}
location /sub2/ {
try_files $uri $uri/ /sub2/index.php?$query_string;
}
# [other sub-apps included in the same way]
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ /\.ht {
deny all;
}
# [ssl stuff]
}
I also tried to replace the separate locations with
location ^~ /(sub1|sub2)/ {
try_files $uri $uri/ /$1/index.php?$query_string;
}`
but didn't succeed with that - this location somehow didn't ever match and everything got passed to the /index.php
in base instead.
Upvotes: 1