Вопрос или проблема
У меня есть следующая конфигурация рабочего виртуального хоста:
server {
listen 443 ssl http2;
server_name example.com;
root /home/sites/example.com/html; #основной каталог для основного домена сайта
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
...
}
Затем я хочу создать подсайт с этой структурой example.com/sub1, но для удобства организации я не хочу, чтобы sub1 находился в /home/sites/example.com/html. Я предпочел бы, чтобы он находился в /home/sites/example.com/subsites. Поэтому я добавляю этот блок location, и он работает.
location /sub1/ {
root /home/sites/example.com/subsites;
....
}
Проблема в том, что если я хочу создать еще один подсайт, мне нужно скопировать этот блок и немного изменить его. Например, для sub2 мне нужно создать каталог с именем sub2 в /home/sites/example.com/subsites и затем добавить блок location, как этот:
location /sub2/ {
root /home/sites/example.com/subsites;
....
}
и я могу получить к нему доступ через example.com/sub2.
Я хочу сделать блок location с использованием регулярных выражений, чтобы каждый раз, когда я создаю каталог в /home/sites/example.com/subsites (dir3, dir4, dir5,… dirN), эти вновь созданные каталоги были доступны через example.com/dir3, example.com/dir4, example.com/dir5,…example.com/dirN. Я пробовал с этим блоком, nginx перезагрузился нормально, но я не могу получить доступ к вновь созданным каталогам и получаю только ошибку 404.
location ~* "/dir([0-9]{1,4})/" {
root /home/sites/example.com/subsites;
}
Это странная проблема, я думаю. В моем .conf
файле есть такие блоки:
location ~* /\.well-known {
allow all;
}
location ~* /\. {
deny all;
}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
location ~* \.(jpg|jpeg|gif|png|css|js|swf|ico|pdf|svg|eot|ttf|woff)$ {
expires 60d;
access_log off;
}
Когда я ставлю этот блок после этих блоков и пытаюсь получить доступ к example.com/dir3 (после создания каталога dir3
в /home/sites/example.com/subsites
), он показывает страницу 404.
location ~* "/dir([0-9]{1,4})/" {
root /home/sites/example.com/subsites;
}
Проблема решается перемещением этого блока выше этих блоков. Я не знаю причины этого, но проблема решена, в любом случае.
Ответ или решение
Для настройки wildcard подкаталогов в Nginx необходимо учитывать особенности работы директив и порядок их обработки. Мы рассмотрим ваш сценарий, используя предоставленные вами данные, а также объясним, почему перемещение блока с регулярным выражением решило вашу проблему.
Проблема и решение
Вы хотите сделать так, чтобы каждый новый подкаталог (например, dir3
, dir4
и т.д.) в директории /home/sites/example.com/subsites
был доступен по адресу example.com/dir3
, example.com/dir4
и так далее. Начальная попытка была выполнена с использованием следующего блока:
location ~* "/dir([0-9]{1,4})/" {
root /home/sites/example.com/subsites;
}
Этот блок должен был соответствовать URL с подкаталогом dir
и цифрами. Однако при добавлении этого блока в конфигурацию Nginx ниже других блоков вы столкнулись с ошибкой 404, что указывает на отсутствие соответствия или неправильную настройку.
Почему это произошло?
В Nginx порядок обработки блоков location
имеет критическое значение. Когда Nginx получает запрос, он проходит по всем определённым блокам и выбирает первый, который соответствует условиям. Если ваш блок с регулярным выражением находится после более общих определений и специфичных правил (например, для .well-known
, доступа и обработки файлов), то Nginx мог выбирать эти блоки раньше, тем самым блокируя доступ к вашим подкаталогам.
Оптимальная конфигурация
Для вашего случая правильная структура должна выглядеть примерно так:
server {
listen 443 ssl http2;
server_name example.com;
root /home/sites/example.com/html;
index index.php index.html index.htm;
# Общий блок для всех подкаталогов
location ~* ^/dir([0-9]{1,4})/ {
alias /home/sites/example.com/subsites;
try_files $uri $uri/ =404;
}
# Ваши другие блоки
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~* /\.well-known {
allow all;
}
location ~* /\. {
deny all;
}
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
location ~* \.(jpg|jpeg|gif|png|css|js|swf|ico|pdf|svg|eot|ttf|woff)$ {
expires 60d;
access_log off;
}
}
Объяснение изменений
-
Порядок блоков: Перемещение блока с регулярным выражением выше других блоков позволяет Nginx своевременно обрабатывать запросы на доступ к подкаталогам
dirN
. Это предотвращает ситуацию, когда более специфичные блоки отказывают в доступе, прежде чем запрос достигнет вашего блока. -
Использование
alias
: В отличие отroot
, директиваalias
позволяет корректно перезаписывать путь запроса на фактический путь к папке на сервере, что важно при работе с подкаталогами. -
try_files
: Эта директива проверяет существование запрашиваемых файлов и предоставляет более детализированный контроль над тем, что происходит, когда ресурс не найден. Если файл не существует, Nginx возвращает 404.
Заключение
Теперь, с правильно настроенным блоком и его местоположением в конфигурации, вы сможете добавлять новые подкаталоги в /home/sites/example.com/subsites
без необходимости изменять конфигурацию сервера. Каждый новый подкаталог автоматически станет доступным по соответствующему URL. Эта конфигурация сделает вашу структуру обслуживающей подкаталоги более гибкой и масштабируемой.