Вопрос или проблема
У меня есть проблема с настройкой NGINX для перенаправления на пользовательскую страницу ошибки в другом месте (включая css, изображения, js), если должна быть вызвана страница ошибки.
Сначала я хотел бы заблокировать доступ к папке (например, .git
). Это можно легко сделать с помощью (внутри блока сервера)
location ~ /(.git) {
deny all;
return 404;
}
Затем я создал элемент error_page
с пользовательским файлом 404.html в другом месте, чем корневая директория веб-сайта.
error_page 404 /404.html;
location = /404.html {
root /var/data/websites/error-page;
internal;
}
После этих изменений моя пользовательская страница 404 будет отображаться, но без css, js и изображений.
Если я проверяю сайт, причина проста: путь к файлам неверен – они основаны на местоположении (в моем примере .git
).
https://it.dmetzler1988.io/.git/css/main.css net::ERR_ABORTED 404
.
Вот полный файл конфигурации NGINX для этой страницы (удалены только пути к сертификатам ssl):
server {
listen 443 ssl;
listen [::]:443 ssl http2;
ssl_certificate <path>;
ssl_certificate_key <path>;
server_name it.dmetzler1988.io;
root /var/data/websites/dmetzler1988.io/it.dmetzler1988.io;
index index.html index.php;
error_page 404 /404.html;
location = /404.html {
root /var/data/websites/error-page;
internal;
}
location ~ /(.git) {
deny all;
return 404;
}
}
Итак, мои вопросы на этом месте:
- Как я могу исправить проблему с неверным путем (удалить
.git
из пути)? - Это правильный способ для такого случая использования, или есть лучшее решение?
Во-первых, об ошибках в вашей конфигурации.
location ~ /(.git) { ... }
Похоже, вы не совсем знакомы с регулярными выражениями PCRE. Нет необходимости использовать здесь группу захвата – группы захвата используются, когда позже нужно использовать ее содержимое. Однако это не критическая ошибка. Самое плохое в том, что вы используете незашитый символ точки, который работает как подстановочный знак в шаблонах регулярных выражений. Таким образом, вы эффективно блокируете любой URI, содержащий строку, где вторым, третьим и четвертым символами являются git
(например, /agitation/index.html
, /any/prefix/agitation/index.html
и т. д.). Правильный шаблон регулярного выражения здесь будет /\.git
(блокировка всего, что начинается с .git
, включая .gitignore
и т. д. на любом уровне вложенности каталогов).
Далее, вы используете две директивы в этом местоположении – deny all
и return 404
. Достаточно будет любой из них – либо deny all
(возвращает HTTP 403 Forbidden
), либо return 404
(возвращает HTTP 404 Not Found
). Причина, по которой вы получаете 404, а не 403, заключается в том, что директива return
выполняется на этапе обработки запроса REWRITE
, а deny
на более позднем этапе ACCESS
(фазы обработки запросов описаны в руководстве по разработке).
Теперь вернемся к вашему вопросу. Похоже, вы ссылаетесь на свои ресурсы, используя относительные пути URI, например
<link rel="stylesheet" type="text/css" href="css/main.css">
Некоторые из ваших вариантов (но не ограничены):
-
включите каждый актив в HTML обработчика ошибок (включая изображения, вы можете сделать это, закодировав свои изображения до BASE64 и используя Data URIs);
-
переместите все активы в некоторую папку под вашим основным веб-каталогом сайта (скажем,
/var/data/websites/dmetzler1988.io/it.dmetzler1988.io/assets/errors
) и указывайте на них, используя полный путь:<link rel="stylesheet" type="text/css" href="/assets/errors/css/main.css">
Как я могу это сделать на своем сервере:
Структура директорий:
/var/www/example.com/public
/var/www/internal
/var/www/internal/400-nginx.html
...
/var/www/internal/504-nginx.html
И внутри моего server{...}
блока:
# Страницы ошибок
# HTTP 400: Неверный запрос
error_page 400 /400-nginx.html;
location = "/400-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 403: Запрещено
error_page 403 /403-nginx.html;
location = "/403-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 404: Не найдено
error_page 404 /404-nginx.html;
location = "/404-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 405: Метод не разрешен
error_page 405 /405-nginx.html;
location = "/405-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 413: Слишком большой объем данных
error_page 413 /413-nginx.html;
location = "/413-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 415: Неподдерживаемый медиа тип
error_page 415 /415-nginx.html;
location = "/415-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 429: Слишком много запросов
error_page 429 /429-nginx.html;
location = "/429-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 501: Метод не реализован
error_page 501 /501-nginx.html;
location = "/501-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 502: Плохой шлюз
error_page 502 /502-nginx.html;
location = "/502-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 503: Сервис недоступен
error_page 503 /503-nginx.html;
location = "/503-nginx.html" {
root var/www/internal;
internal;
}
# HTTP 504: Тайм-аут шлюза
error_page 504 /504-nginx.html;
location = "/504-nginx.html" {
root var/www/internal;
internal;
}
.
Ответ или решение
Решение проблемы с доступом и переадресацией на пользовательскую страницу ошибки в NGINX может быть более сложным, чем кажется на первый взгляд. Основная задача заключается в правильной настройке серверного блока, чтобы обеспечить корректное отображение страницы ошибки с подключенными стилями и скриптами. Давайте проведем детальный разбор.
Ваша текущая конфигурация
Вы настроили блокировку доступа к определенной директории, например, .git
, и перенаправили пользователей на настраиваемую страницу ошибки. Однако стили и скрипты не подгружаются правильно, поскольку используются относительные пути.
Ошибки в настройках:
-
Регулярное выражение: Вы используете необработанный символ
.
в выражении/(.git)
, который в PCRE (Perl Compatible Regular Expressions) обозначает любой символ. Поэтому ваше правило может срабатывать не так, как ожидается. Используйте безопасный вариант —\.git
, чтобы блокировать только каталоги, начинающиеся с.git
. -
Двойная инструкция в блоке: У вас одновременно используются
deny all;
иreturn 404;
. Это избыточно. Достаточно оставить толькоreturn 404;
для возвращения ошибки 404 Not Found, или же оставитьdeny all;
, если хотите возвращать 403 Forbidden.
Исправление путей на странице ошибки
Ошибки с неправильными путями к файлам возникают из-за относительной адресации. Чтобы исправить это, у вас есть несколько возможностей:
-
Использование абсолютных путей: Переместите необходимые ресурсы (CSS, изображения, JS) в отдельную директорию под основным корнем сайта и замените относительные пути на абсолютные. Например, если ваши ресурсы перемещены в
/assets/errors
, то путь будет таким:<link rel="stylesheet" type="text/css" href="/assets/errors/css/main.css">
. -
Инлайн-стили и скрипты: Вы можете инлайнить CSS и JavaScript непосредственно в HTML-код страницы ошибки. Для изображений можно использовать Data URIs, что позволит избежать проблемы с путями вообще.
Общий подход к настройке страниц ошибок
В качестве примера, вы можете рассмотреть создание единой структуры для хранения всех страниц ошибок. Это поможет централизовать изменения и управлять их отображением проще.
Пример структуры директорий:
/var/www/example.com/public
/var/www/internal
/var/www/internal/errors
/var/www/internal/errors/404.html
Настройка серверного блока:
server {
listen 443 ssl;
listen [::]:443 ssl http2;
server_name it.dmetzler1988.io;
root /var/data/websites/dmetzler1988.io/it.dmetzler1988.io;
index index.html index.php;
error_page 404 /errors/404.html;
location = /errors/404.html {
root /var/www/internal;
internal;
}
location ~ /\.git {
return 404;
}
location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ {
expires 1M;
add_header Cache-Control "public";
}
}
Заключение
Внедрение изменений, предложенных выше, должно решить вашу проблему. Убедитесь, что относительные пути заменены на абсолютные или используйте инлайн-стили для упрощения управления. Это повышает не только безопасность вашего сайта, но и улучшает его производительность и пользовательский опыт.
Удачи в настройке! Если возникнут дополнительные вопросы, всегда готов помочь.