Почему .htaccess не работает: 500, 403, 404, бесконечный редирект — и как чинить
Самые частые жалобы на .htaccess: «после правки сайт отдаёт 500», «403 Forbidden», «включил ЧПУ — всё стало 404», «бесконечный редирект», «правлю файл, а ничего не меняется». Ниже — для каждого симптома список причин и что конкретно делать. Почти всегда первый шаг один и тот же: открыть error.log сервера — там обычно точная строка и причина. С этого и начнём — см. раздел про диагностику, а в конце — чеклист по порядку.
Важно: .htaccess работает только на Apache (и на LiteSpeed Enterprise, который его эмулирует). На nginx, Caddy, OpenLiteSpeed файл .htaccess не читается вообще — там настройки задаются в конфиге сервера. Если вы не уверены, какой у вас сервер, — это первое, что стоит выяснить (см. раздел «.htaccess вообще не действует»).
1. Первым делом: как увидеть, что не так
90% проблем с .htaccess диагностируются за минуту, если знать, куда смотреть.
- Откройте
error.log— там почти всегда точная строка файла и причина. Где он: в cPanel — «Metrics → Errors» или файл~/logs/; в ISPmanager — раздел «Журналы»; в Plesk — «Logs» сайта; на VPS / выделенном —/var/log/apache2/error.log(Debian / Ubuntu) или/var/log/httpd/error_log(CentOS / RHEL), для конкретного сайта — путь из директивыErrorLogв его vhost. - Как читать запись: ищите имя своего
.htaccessи сообщения видаInvalid command 'php_flag', perhaps misspelled or defined by a module not included in the server configuration,… not allowed here,client denied by server configuration,Request exceeded the limit of 10 internal redirects. - Метод бинарного поиска: закомментируйте (
#в начале строк) половину.htaccess, обновите страницу; если ошибка пропала — проблема в закомментированной половине, делите дальше. - Отладка rewrite:
LogLevel alert rewrite:trace3печатает каждый шагmod_rewriteвerror.log— но это директива конфига сервера / vhost, в.htaccessне работает; на хостинге используйте тестер /rewrite/ (пошаговая трассировка правил). - Инструменты: линтер /check/ — находит ошибки синтаксиса, неподдерживаемые / устаревшие директивы,
php_valueна FPM, опечатки в именах; тестер /rewrite/ — что матчится и куда переписывается на конкретном URL.
Подробный гид по отладке — статья «Отладка .htaccess: error_log, rewrite:trace».
2. 500 Internal Server Error
Сайт или один раздел отдаёт «500 Internal Server Error» сразу после добавления или правки .htaccess. Почти всегда — ошибка в самом файле.
Причины:
- Синтаксическая ошибка или опечатка в директиве: лишняя кавычка, неизвестное слово, незакрытый
<IfModule>/<FilesMatch>. - Неподдерживаемая директива:
php_value/php_flagна PHP-FPM / FastCGI (Invalid command 'php_flag');Options …без разрешённогоAllowOverride Options(Options not allowed here) (подробнее — статья «AllowOverride…»);Order/Allow/Denyна Apache 2.4 без модуляmod_access_compat. - Модуль не загружен:
RewriteEngineбезmod_rewrite,Header …безmod_headers,ExpiresByTypeбезmod_expires— лечится обёрткой<IfModule mod_xxx.c> … </IfModule>. - Кодировка или перевод строк: BOM в начале файла, не-UTF-8, иногда CRLF — пересохраните файл как UTF-8 без BOM с переводами строк LF.
- Бесконечная внутренняя рекурсия rewrite-правил (
Request exceeded the limit of 10 internal redirects) — обычно правило, переписывающее URL само на себя без условия-страховки.
Как чинить:
- Первым делом —
error.log: там точная строка и причина (см. раздел 1). - Прогнать файл через линтер /check/.
- Обернуть «рискованные» директивы в
<IfModule>. - Настройки PHP на FPM — через
.user.iniв корне сайта или панель хостинга (подробнее — /performance/ и /security/ → hardening PHP). - Если ничего не помогает — закомментировать весь файл и возвращать строки по частям.
# вызовет 500 на PHP-FPM / FastCGI: php_flag display_errors Off # безопаснее (только для mod_php), не уронит сервер на FPM: <IfModule mod_php.c> php_flag display_errors Off </IfModule> # на PHP-FPM настройки PHP — в .user.ini в корне сайта: # display_errors = Off
3. 403 Forbidden
Сервер отдаёт «403 Forbidden / You don't have permission to access …» — доступ запрещён где-то в конфигурации.
Причины:
Require all denied/Deny from allв этом или родительском.htaccess(либо в конфиге сервера) — закрыли больше, чем хотели.Options -Indexesи в каталоге нетindex.php/index.html— запросили сам каталог.- Права доступа: каталог не
755, файл не644, либо неверный владелец / группа (после загрузки по FTP или распаковки архива). <FilesMatch>/<Files>со слишком широким regex зацепил нужные файлы.Require ip …/ IP-фильтр не включает ваш текущий адрес (особенно за прокси или мобильным интернетом).- WAF / mod_security хостинга заблокировал запрос — тогда в
error.logбудетModSecurity: Access denied.
Как чинить:
- Просмотреть все
.htaccessот корня document root до нужного файла на предметdenied/Deny. error.log:client denied by server configuration,AH01797,ModSecurity.- Проверить и выставить права (
755на каталоги,644на файлы) через FTP / SSH. - Сузить regex в
<FilesMatch>; линтер /check/ подсвечивает подозрительно широкие маски. - Правильно настроить доступ по IP / паролю — центр безопасности.
4. 404 после включения ЧПУ (mod_rewrite)
Добавили правила «человекопонятных URL» — и теперь все такие адреса отдают 404, хотя главная работает.
Причины:
- Есть
RewriteRule, но нетRewriteEngine On(или он стоит ниже правил) — все правила игнорируются. mod_rewriteне включён на хостинге.- Неправильный
RewriteBase— сайт в подкаталоге, а база не указана или указана неверно. - Фронт-контроллер-правило без проверки «файл / каталог не существует» (
!-f/!-d) — переписывает вindex.phpв том числе существующие ассеты. Options +MultiViews(mod_negotiation) перехватывает запрос раньшеmod_rewrite— выключите:Options -MultiViews.- Файл или маршрут, на который переписываем, действительно не существует (опечатка в подстановке).
Как чинить:
RewriteEngine On— первой строкой блока rewrite.- Проверить модуль:
apachectl -M | grep rewrite, либоphpinfo()→apache2handler→Loaded Modules. - В подкаталоге добавить
RewriteBase /подкаталог/. - Использовать типовой безопасный фронт-контроллер (см. блок ниже).
- Проверить правила на конкретном URL — тестер /rewrite/; как устроен
mod_rewrite— туториал «Как работает mod_rewrite».
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php [L]
WP-специфика ЧПУ (блок # BEGIN WordPress) — хаб «.htaccess для WordPress».
Фреймворк-специфика ЧПУ (Laravel/Symfony/Joomla/…) — хаб «.htaccess для CMS и фреймворков».
5. Бесконечный редирект (ERR_TOO_MANY_REDIRECTS)
Браузер пишет «слишком много перенаправлений» / в error.log — Request exceeded the limit of 10 internal redirects. Правило заворачивает запрос по кругу.
Причины:
- HTTPS-редирект за прокси / CDN: до Apache доходит уже расшифрованный трафик,
%{HTTPS}всегдаoff, правило бесконечно редиректит «на https» — нужно проверять%{HTTP:X-Forwarded-Proto}. - Два конфликтующих правила www↔без-www (или
.htaccess+ настройка CMS / панели): одно ведёт наwww, другое — обратно. RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]без условия — срабатывает, даже когда ужеhttps.DirectoryIndex/ErrorDocument, указывающий сам на себя или на несуществующий обработчик.- Правило, добавляющее / убирающее завершающий
/, без условия — добавляет и тут же убирает.
Как чинить:
- В DevTools (вкладка Network) посмотреть цепочку
301/302— видно, кто на кого ведёт. - Проверить реальную цепочку для конкретного URL — /redirect-check/.
- Добавить условие-страховку, чтобы правило не срабатывало повторно (см. блок ниже).
- За CDN / прокси проверять
%{HTTP:X-Forwarded-Proto}, а не%{HTTPS}. - Убедиться, что одно и то же перенаправление не настроено и в
.htaccess, и в CMS / панели одновременно.
RewriteEngine On # редирект на HTTPS, который работает и за CDN/прокси RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
6. .htaccess вообще не действует
Правки в .htaccess не дают никакого эффекта — ни ошибки, ни нового поведения. Скорее всего файл просто не читается.
Причины:
- Сервер — не Apache. На nginx, Caddy, OpenLiteSpeed
.htaccessне читается в принципе — настройки делаются в конфиге сервера. (LiteSpeed Enterprise — читает; nginx + «эмуляция .htaccess» в некоторых панелях — частично.) AllowOverride Noneв конфиге сервера / vhost — на VPS это частый дефолт;.htaccessесть, но Apache его не применяет.- Файл не в том каталоге — нужен в корне document root (или в нужной папке), а лежит, например, на уровень выше.
- Файл назван неверно:
htaccess.txt,.htaccess.txt,htaccess, или сохранён не как обычный текст. Windows по умолчанию прячет расширения —.htaccessлегко оказывается.htaccess.txt. - Ответ закэширован прокси / CDN — вы видите старую версию страницы, а не результат нового
.htaccess.
Если у вас nginx — перевести правила .htaccess в nginx-конфиг поможет конвертер .htaccess → nginx (примерный перевод — проверяйте вручную).
Подробно про разные хостинги и панели (cPanel, ISPmanager, Plesk, Beget, LiteSpeed, nginx-only) — хаб «.htaccess на разных хостингах».
Как проверить:
- Добавьте первой строкой
.htaccessзаведомо неверную команду — напримерESJDKLKJ— и обновите страницу. Появилась500 Internal Server Error→ файл читается (проблема в другом разделе этого гида). Не появилась → файл не читается, причины 1–4 выше. - Уточнить у хостинга тип сервера и значение
AllowOverride. - Проверить имя и расположение файла по FTP (включить показ расширений).
- Сбросить кэш CDN. Прогнать файл через линтер /check/.
7. Конкретное RewriteRule не срабатывает (а другие — да)
Одно правило mod_rewrite не применяется, хотя RewriteEngine On стоит и соседние правила работают.
Причины:
- Паттерн не матчит из-за ведущего
/: в.htaccessпуть приходит без начального слэша (about/), а в<Directory>/ vhost — с (/about/); пишите^about/или^/?about/. - Предыдущее правило с
[L](или[END]) уже остановило обработку — до этого правила запрос не дошёл. RewriteCondдействует только на самый ближайший следующийRewriteRule; между ними нельзя вставлять другиеRewriteRule.- Не экранированы спецсимволы regex:
.— это «любой символ»,?/+/(тоже метасимволы; пишите\.,\?. - Query-string в паттерн
RewriteRuleне входит —?id=5нельзя матчить вRewriteRule, нуженRewriteCond %{QUERY_STRING} …(и флаг[QSA], чтобы старый query не потерялся). - Относительная подстановка без
RewriteBaseв.htaccessподкаталога — Apache не знает префикс. - Регистр не совпадает, а флага
[NC]нет.
Как чинить:
- Прогнать правило в тестере /rewrite/ — он показывает пошагово, что матчится и почему.
- Убрать промежуточные
RewriteRuleмеждуRewriteCondи нужным правилом. - Проверить, нет ли
[L]в правилах выше. - Справка по синтаксису regex и флагов — туториал «Как работает mod_rewrite» и справочник директив mod_rewrite.
8. Чеклист: .htaccess не работает — проверь по порядку
- Сервер точно Apache (или LiteSpeed Enterprise)? На nginx
.htaccessне работает. — раздел 6 - Файл реально называется
.htaccess(без.txt) и лежит в нужном каталоге? — раздел 6 - Хостинг разрешает
.htaccess? ДобавьESJDKLKJпервой строкой — должна появиться 500; если нет —.htaccessне читается. — раздел 6 - Что в
error.log? Там почти всегда точная строка и причина. — раздел 1 - Если 500 — какая директива виновата? Оберни в
<IfModule>или убери;php_value/php_flagна FPM не работает. — раздел 2, /check/ - Если ЧПУ дают 404 — есть
RewriteEngine Onпервой строкой? Включёнmod_rewrite? — раздел 4 - Если бесконечный редирект — сайт за CDN / прокси? Проверь
%{HTTP:X-Forwarded-Proto}, а не%{HTTPS}. — раздел 5 - Прогони файл через линтер /check/, а правила
mod_rewrite— через тестер /rewrite/. — раздел 1
9. Ссылки и инструменты
- Сайт уже лёг — экстренная пошаговая шпаргалка «сайт упал после правки .htaccess».
- Линтер .htaccess — ошибки синтаксиса, неподдерживаемые / устаревшие директивы, опечатки.
- Аудит безопасности .htaccess — проверить файл на опасные настройки и пробелы в защите.
- RewriteRule-тестер — пошаговая трассировка правил на конкретном URL.
- «Как работает mod_rewrite» — туториал по синтаксису и поведению.
- Справочник директив — что делает каждая директива, синтаксис, пример.
- Конвертер 2.2↔2.4 — если ошибка из-за
Order/Allow/Deny. - Центр безопасности — 403, доступ по IP / паролю, защита файлов.
- Ускорение сайта — кэш, gzip,
php_valueна FPM. - Рецепты .htaccess · генератор .htaccess — готовые проверенные блоки.