Перейти к содержимому

Файл .htaccess - что работает, что игнорируется, что роняет сайт

Файл .htaccess в корне сайта задаёт правила Apache: обработку адресов ЧПУ, страницу ошибки и настройки PHP. На площадке с nginx впереди он читается не для каждого запроса, а одна неверная строка внутри роняет сайт целиком.

Решение

Проверяем, читается ли файл

Убеждаемся, что запрос доходит до Apache:

Окно терминала
# заведомо неверная строка: если файл читается, ответ сменится на 500
printf 'ThisDirectiveDoesNotExist on\n' >> /home/bitrix/www/.htaccess
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
sed -i '$d' /home/bitrix/www/.htaccess # строку убираем сразу же
grep -rn 'AllowOverride' /etc/httpd/conf.d/ # None означает, что файл не читают

Код 500 означает, что сервер файл прочитал и разобрал. Прежний код ответа означает обратное: запрос обслуживает один nginx либо переопределение запрещено. Тот же вердикт печатает штатная проверка системы строкой «Обработка .htaccess».

Что приходит с поставкой

Открываем корневой файл дистрибутива:

Options -Indexes
ErrorDocument 404 /404.php
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f # существующий файл отдаём как есть
RewriteCond %{REQUEST_FILENAME} !-l # символическую ссылку тоже
RewriteCond %{REQUEST_FILENAME} !-d # и существующий каталог
RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L] # остальное - обработчику ЧПУ
</IfModule>

Убрать любое из трёх условий - значит гонять через PHP ещё и картинки со стилями. Заменить цель на /index.php тоже нельзя: правила ЧПУ комплексные компоненты пишут именно в /bitrix/urlrewrite.php.

Ставим свои правила адресов

Точечные переходы кладём выше блока ЧПУ:

RewriteCond %{REQUEST_URI} !^/bitrix/ # служебные пути не трогаем
RewriteRule ^info/faq/ https://example.com/ [R=301,L]
RewriteRule ^info/ https://example.com/ [R=301,L]

Правила читаются сверху вниз, поэтому вложенный адрес обязан идти раньше общего. Условие про служебный каталог спасает обмен и платёжные обработчики: без него внешний сервис получает переход вместо ответа.

Убираем директивы настроек PHP

Настройки интерпретатора закрываем проверкой модуля:

<IfModule mod_php7.c>
php_flag session.use_trans_sid off # идентификатор сессии не пишем в адрес
php_value memory_limit 256M # вне модуля эта строка даёт 500
</IfModule>

Директивы php_value и php_flag понимает только PHP как модуль Apache. При работе через отдельный обработчик FastCGI или PHP-FPM та же строка без обёртки даёт 500 на каждый запрос. Пределы времени исполнения и размера запроса при FPM задаёт конфигурация пула, и правкой php.ini их не обойти.

Отличаем файл прав платформы

Права разделов живут в другом файле с похожим именем:

<?php
$PERM["admin"]["*"] = "D"; // всем группам запрет
$PERM["admin"]["1"] = "R"; // группа администраторов читает
$PERM["/"]["*"] = "R"; // корень раздела открыт на чтение

Файл .access.php читает платформа в прологе, а .htaccess - веб-сервер ещё до запуска PHP. Первый закрывает раздел от групп пользователей, второй отсекает сам запрос до платформы.

Переносим и обновляем

После переноса сверяем имя файла и права:

Окно терминала
ls -la /home/bitrix/www/ | grep -i htaccess # ищем префикс подчёркивания
find /home/bitrix/www -mindepth 2 -name '.htaccess' -ls
chmod 644 /home/bitrix/www/.htaccess

Восстановление из копии умеет переименовать корневой файл в _.htaccess, и тогда ЧПУ отваливается молча. Обновления платформы этот файл не трогают: он считается пользовательским.

Проверяем результат запросом

Проверяем адрес ЧПУ и журнал сервера:

Окно терминала
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/catalog/tovar/
curl -sIL https://example.com/info/faq/ | grep -iE 'HTTP/|location'
tail -20 /var/log/httpd/error_log | grep -i htaccess # неразрешённые директивы

Статику nginx отдаёт сам, минуя Apache, поэтому заголовки кеширования из блока mod_expires до картинок не доходят. Их задают в конфигурации фронтенда.

Типичные проблемы

Сайт отдаёт 500 сразу после правки файла.

Внутрь попала директива, которую сервер не разрешает или не понимает в текущей сборке. Точную строку называет журнал ошибок веб-сервера, а сама страница о ней молчит.

Проверка системы пишет «Обработка .htaccess: Нет».

Запрос до Apache не доходит либо переопределение запрещено директивой AllowOverride. Правила файла в этом состоянии не работают, хотя он лежит на своём месте.

ЧПУ перестал работать после переноса сайта.

Корневой файл потерял имя: восстановление из копии дописало ему подчёркивание спереди. Без правила переадресации адреса разделов упираются в 404 самого веб-сервера.

Файл .htaccess появился в каждом разделе сайта.

Поставка такие файлы не создаёт, их кладёт вредонос с запретом на выполнение скриптов. Разделы сайта и админка при этом начинают отвечать кодом 403.

Переход уводит на склеенный адрес вида example.rufaq.

Правило написано директивой Redirect, а она дописывает остаток пути к цели назначения. Для точечных переходов берут RewriteRule с флагом R=301.

Частые вопросы

Почему в каждом разделе битрикса находится файл .htaccess?

Дистрибутив кладёт его только в корень и в служебные каталоги ядра. Копия в каждом разделе с блоком Deny from all внутри - типичный след взлома, и разбор переходит от правил веб-сервера к чистке сайта.

Как изменить настройки PHP через .htaccess?

При PHP-FPM никак: директивы php_value и php_flag валидны только для модуля Apache и дают 500. Значения меняют в php.ini, а пределы времени исполнения и размера запроса - в конфигурации пула обработчика.

Работает ли файл, если сайт живёт только на nginx с PHP-FPM?

Нет, nginx его не читает вовсе. Правила обработки адресов, запреты и страницы ошибок переносят в конфигурацию сервера руками, иначе ЧПУ и защита служебных путей пропадают молча.

Где править файл, если доступ к админке потерян ошибочным правилом?

Через файловый менеджер хостинга, по SFTP или в консоли сервера. Имя начинается с точки, поэтому в списке файл виден только с включённым показом скрытых.

Перезапишет ли обновление платформы мои правила?

Корневой файл считается пользовательским, и обновления его не трогают. Перезапись случается при установке дистрибутива поверх и при восстановлении из резервной копии.

Смежное

Первоисточник