Что такое .htaccess и зачем он нужен сайту: подробное руководство с примерами для WordPress, 1С-Битрикс и других CMS

Содержание
  1. 1. Что такое .htaccess
  2. 1.1. Простое объяснение
  3. 1.2. Для чего он нужен
  4. 1.3. Почему CMS нужен файл с правилами
  5. 1.4. Когда сайт может обойтись без .htaccess
  6. 2. Где .htaccess работает и где не работает
  7. 2.1. Apache
  8. 2.2. Nginx
  9. 2.3. Nginx перед Apache
  10. 2.4. LiteSpeed и OpenLiteSpeed
  11. 2.5. IIS, облачные платформы и конструкторы
  12. 2.6. Почему заголовок Server не дает полной картины
  13. 3. Где находится .htaccess и как его создать
  14. 3.1. Корень сайта и корень проекта — не всегда одно и то же
  15. 3.2. Почему файл не виден
  16. 3.3. Правильное имя и кодировка
  17. 3.4. Права доступа и владелец
  18. 3.5. Резервная копия и мгновенный откат
  19. AllowOverride, модули и наследование
  20. Почему файл может существовать, но не работать
  21. Модули: почему одинаковые файлы ведут себя по-разному
  22. Наследование — не простое склеивание файлов
  23. Options и символические ссылки
  24. Синтаксис и базовые директивы
  25. Как читать конфигурацию
  26. Три разных значения слова «путь»
  27. Индексный файл и доступ к каталогу
  28. Как работает mod_rewrite: от простого правила к маршрутизации CMS
  29. Включение механизма и структура правила
  30. Регулярные выражения без лишней магии
  31. Условия RewriteCond и логика AND/OR
  32. Флаги, которые полезно понимать
  33. Query string: параметры не входят в шаблон пути
  34. REQUEST_URI и THE_REQUEST: как не перенаправить собственный rewrite
  35. RewriteBase, слеши и подкаталоги
  36. Кодирование URL и опасные универсальные правила
  37. Редиректы, HTTPS и канонические адреса
  38. Простой перенос страницы
  39. HTTPS и единый домен одним переходом
  40. HTTPS за reverse proxy или CDN
  41. Завершающий слеш, регистр и старые URL
  42. Порядок важнее количества правил
  43. Защита файлов и ограничение доступа
  44. Запрет просмотра содержимого каталога
  45. Защита отдельных служебных файлов
  46. Закрытые каталоги и скрытые пути
  47. Ограничение доступа по IP
  48. Пароль на тестовый сайт
  49. IP и пароль одновременно
  50. Запрет исполнения PHP в загрузках
  51. Чего не стоит ожидать от блокировок ботов и Referer
  52. Заголовки, MIME-типы и политика браузера
  53. Как работает Header
  54. HSTS
  55. CSP и защита от встраивания
  56. CORS
  57. MIME и кодировка
  58. Кеширование и сжатие: что действительно ускоряется
  59. Кеш браузера не равен кешу CMS
  60. Умеренное кеширование статики
  61. Какие ответы нельзя кешировать как публичные
  62. ETag, Last-Modified и 304
  63. Сжатие текстовых ресурсов
  64. Ошибки, параметры PHP и режим обслуживания
  65. Собственная страница 404
  66. PHP: mod_php, CGI и PHP-FPM
  67. Режим обслуживания с корректным 503
  68. WordPress: как устроен .htaccess и что разрешено менять
  69. Зачем он нужен WordPress
  70. Базовый блок для обычного сайта в корне домена
  71. Что означают BEGIN WordPress и END WordPress
  72. Как WordPress создаёт и обновляет файл
  73. WordPress в подкаталоге: два разных случая
  74. Multisite: почему обычного блока недостаточно
  75. Плагины кеширования, безопасности и SEO
  76. REST API, XML-RPC, AJAX и Application Passwords
  77. Защита wp-config.php и загрузок
  78. Когда после смены ссылок появляются 404
  79. 1С-Битрикс: подробный разбор .htaccess
  80. Область применения: «Управление сайтом», коробочные продукты и облачные сервисы
  81. Где находится файл и почему одного корневого .htaccess недостаточно
  82. Типичный механизм маршрутизации
  83. Что делает каждая строка
  84. Чем отличаются /bitrix/urlrewrite.php и /urlrewrite.php
  85. ЧПУ компонентов и реальная структура каталогов
  86. Правильные 404 в Битрикс
  87. Редиректы в Битрикс: порядок решает
  88. HTTPS, Nginx и BitrixVM/BitrixEnv
  89. Композитный сайт: почему .htaccess не управляет всем кешированием
  90. Обмен с 1С и HTTP-авторизация
  91. .access.php — не .htaccess
  92. Каталог upload, резервные копии и служебные файлы
  93. План диагностики проблем Битрикс после переноса
  94. .htaccess в других распространённых CMS и платформах
  95. Joomla
  96. Drupal
  97. OpenCart
  98. PrestaShop
  99. Magento Open Source и Adobe Commerce
  100. MODX Revolution
  101. TYPO3
  102. DLE и другие PHP-CMS
  103. Laravel и Symfony: не CMS, но важный смежный случай
  104. Облачные CMS и конструкторы
  105. Диагностика: что делать, если .htaccess не работает
  106. Сначала определите слой, на котором возникла ошибка
  107. Типичные симптомы
  108. Безопасная проверка обработки файла
  109. Команды curl
  110. Журналы Apache и трассировка rewrite
  111. Почему apachectl -t недостаточно
  112. Минимальный набор проверок после изменения
  113. Как организовать правила и внедрять изменения
  114. Не существует одного идеального .htaccess для всех сайтов
  115. Изменения небольшими шагами
  116. Разделяйте автоматические и ручные блоки
  117. Когда лучше отказаться от .htaccess
  118. Частые вопросы и распространённые мифы
  119. Обязателен ли .htaccess для каждого сайта?
  120. Это файл WordPress или Apache?
  121. Можно ли просто скачать чужой файл?
  122. Нужно ли перезапускать Apache?
  123. Поможет ли chmod 777?
  124. Можно ли удалить .htaccess, если сайт работает?
  125. Защищает ли Options -Indexes от скачивания файлов?
  126. Запрет в robots.txt делает файл закрытым?
  127. Можно ли скрыть технологию сайта с помощью .htaccess?
  128. Улучшит ли .htaccess SEO сам по себе?
  129. Нужно ли запрещать всем поисковым роботам параметры URL?
  130. Можно ли заменить WAF набором RewriteCond?
  131. Почему на локальном сервере работает, а на хостинге нет?
  132. Можно ли настроить PHP CLI или cron через .htaccess?
  133. Что важнее: .htaccess или настройки CMS?
  134. Краткий словарь
  135. Итоги

.htaccess — небольшой текстовый файл, который способен изменить поведение целого сайта. С его помощью настраивают понятные адреса страниц, перенаправления, ограничения доступа, HTTP-заголовки, кеширование и обработку ошибок. Но одна неудачная строка может сделать сайт недоступным, нарушить оплату заказа или создать бесконечный цикл редиректов.

Чтобы работать с .htaccess уверенно, недостаточно собрать «полезные правила» из нескольких инструкций. Нужно понимать, какой сервер обрабатывает запрос, где находится файл, в каком порядке выполняются правила и какую часть работы берет на себя CMS.

Это руководство рассчитано и на владельцев сайтов, и на разработчиков. Сначала разберем устройство .htaccess, затем практические настройки и диагностику, после этого — особенности популярных CMS. Наиболее подробно рассмотрим WordPress и «1С-Битрикс: Управление сайтом».

Область применимости. Основные примеры рассчитаны на Apache HTTP Server 2.4, обычное сопоставление URL с каталогами сайта и разрешенную обработку .htaccess. Это учебные фрагменты, а не единый файл, который нужно целиком скопировать на сервер. Требования конкретного хостинга, обработчика PHP и версии CMS имеют приоритет. Домены example.com и адреса из тестовых диапазонов в примерах необходимо заменить своими.

1. Что такое .htaccess

1.1. Простое объяснение

.htaccess — файл распределенной конфигурации Apache. Он позволяет менять разрешенные настройки веб-сервера для определенного каталога и, с учетом правил наследования, его подкаталогов без редактирования основного конфигурационного файла сервера.

Представим запрос https://example.com/catalog/chairs/. Сервер должен решить, существует ли такой каталог, нужно ли передать запрос PHP, разрешен ли доступ посетителю и требуется ли перенаправление. Часть этих решений может задаваться в .htaccess.

Сам файл не является PHP-скриптом, не выполняется браузером и не содержит HTML страницы. Его читает сервер. Посетитель получает результат применения правил: страницу, редирект, ошибку или иной HTTP-ответ.

Название исторически связывают с hypertext access. Точка в начале имени делает файл скрытым во многих Unix-подобных средах, но не обеспечивает защиту сама по себе.

1.2. Для чего он нужен

Типовые задачи .htaccess:

  • направлять человекопонятные URL на обработчик CMS;
  • перенаправлять старые адреса на новые;
  • задавать единый домен и HTTPS;
  • закрывать служебные файлы и каталоги;
  • ограничивать доступ по IP или паролю;
  • управлять индексными файлами и страницами ошибок;
  • задавать поддерживаемые HTTP-заголовки;
  • настраивать кеширование и сжатие ответов;
  • указывать MIME-типы;
  • задавать некоторые параметры PHP, но только при подходящем способе его подключения.

При этом .htaccess не исправляет уязвимый код приложения, не заменяет обновления CMS, не очищает зараженный сайт и не делает медленные SQL-запросы быстрыми.

1.3. Почему CMS нужен файл с правилами

В адресе /blog/what-is-htaccess/ обычно нет реального файла с таким именем. Сервер передает запрос входному PHP-скрипту, а CMS находит нужную запись и формирует страницу.

Такая схема называется front controller: множество URL обслуживает одна точка входа. В WordPress это обычно index.php. В классической схеме ЧПУ 1С-Битрикс запросы к несуществующим физическим путям направляются в /bitrix/urlrewrite.php.

ЧПУ — человекопонятный URL. Сам .htaccess не придумывает адреса записей, не хранит контент и не определяет структуру каталога товаров. Он лишь доставляет запрос нужному обработчику.

1.4. Когда сайт может обойтись без .htaccess

Файл не обязателен для любого сайта. Статический сайт может работать без него. На собственном сервере аналогичные правила часто задают в конфигурации виртуального хоста. На Nginx используются совершенно другие директивы. Управляемый хостинг может настраивать маршрутизацию централизованно.

Поэтому отсутствие .htaccess не доказывает ошибку, а его наличие не доказывает, что сервер действительно его читает.

2. Где .htaccess работает и где не работает

2.1. Apache

Это основная среда применения .htaccess. Но Apache должен разрешать соответствующие переопределения для каталога, а необходимые модули должны быть загружены.

Например, RewriteRule требует mod_rewrite, Header — mod_headers, ExpiresByType — mod_expires. Само существование файла не включает эти модули.

2.2. Nginx

Nginx не интерпретирует .htaccess. Правила задаются в конфигурации server и location. Если сайт обслуживается Nginx и PHP-FPM без Apache, изменения .htaccess не повлияют на обработку запросов.

Простой пример маршрутизации приложения в Nginx может использовать try_files, но механическая замена одной строки Apache на одну строку Nginx небезопасна: отличаются порядок обработки, контексты и правила передачи PHP-запросов.

2.3. Nginx перед Apache

Распространенная архитектура: Nginx принимает внешние запросы, самостоятельно отдает часть статики, а динамические запросы передает Apache.

В этом случае .htaccess действует только там, где запрос действительно дошел до Apache. Если Nginx отдает резервный архив напрямую, запрет в Apache не защитит архив. Если Nginx кеширует ответ, посетитель может получить старый вариант, не обращаясь к Apache вообще.

Это особенно важно для загрузок пользователей, конфиденциальных файлов, кеша, HTTP-заголовков и ограничения доступа к служебным путям.

2.4. LiteSpeed и OpenLiteSpeed

LiteSpeed Web Server поддерживает существенную часть Apache-совместимых настроек, но совместимость зависит от директив и конфигурации. Нельзя считать любую конструкцию Apache автоматически переносимой.

OpenLiteSpeed — отдельный продукт. Его поддержка правил перезаписи из .htaccess не означает полноценную поддержку всех директив Apache; порядок применения изменений также нужно сверять с настройками сервера. Ограничения доступа, заголовки и PHP-настройки нельзя переносить вслепую.

2.5. IIS, облачные платформы и конструкторы

В IIS обычно используется web.config. В управляемых сервисах часть серверных настроек доступна через панель или недоступна вовсе. Shopify, Wix и подобные SaaS-платформы не предоставляют обычному владельцу сайта корневой .htaccess для произвольной настройки сервера.

Для WordPress.com доступность инфраструктурных настроек зависит от среды и возможностей сервиса; инструкции для самостоятельно установленного WordPress нельзя автоматически переносить на него.

2.6. Почему заголовок Server не дает полной картины

Заголовок Server может быть скрыт, изменен или принадлежать только внешнему прокси. Даже если в нем написано nginx, за ним может находиться Apache. Надежнее проверить панель хостинга, конфигурацию и логи либо уточнить архитектуру у администратора.

3. Где находится .htaccess и как его создать

3.1. Корень сайта и корень проекта — не всегда одно и то же

Обычно основной файл находится в публичном корне сайта — DocumentRoot. Каталог может называться public_html, www, htdocs, public, web или иначе.

Если корень проекта — /srv/project, а посетителям доступен только /srv/project/public, серверный файл для публичных URL обычно размещают в public. В некоторых конфигурациях могут также обрабатываться файлы в родительских каталогах, поэтому проверять нужно всю разрешенную цепочку каталогов.

В WordPress файл часто лежит рядом с index.php, wp-admin и wp-content. В 1С-Битрикс — в корне публичной части рядом с каталогами bitrix, local, upload и файлом index.php. Реальная структура установки может отличаться.

3.2. Почему файл не виден

Файловый менеджер или FTP-клиент может скрывать имена, начинающиеся с точки. Включите показ скрытых файлов. В терминале используйте:

ls -la /path/to/site
Bash

Если файла нет, сначала проверьте, должен ли он быть в этой архитектуре. Не создавайте его только потому, что он встречается в инструкции для другого сервера.

3.3. Правильное имя и кодировка

Имя должно быть ровно .htaccess, без .txt, пробелов и дополнительной точки. Практичный формат — обычный текст в UTF-8 без BOM и с переводами строк LF. BOM и невидимые символы способны превратить корректную директиву в неизвестную.

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

3.4. Права доступа и владелец

Часто для файла достаточно прав 644, но это не универсальный рецепт: важны владелец, группа, ACL, модель PHP и требования хостинга. Сервер должен читать файл и проходить по родительским каталогам. Запись следует разрешать только тем пользователям и процессам, которым она действительно нужна.

chmod 777 .htaccess — не способ безопасно решить проблему. Если CMS не может обновить правила, разберитесь с владельцем и моделью доступа либо сохраните правила вручную через доверенный канал.

Не стоит автоматически ставить 444: это может помешать штатному обновлению настроек, но не защитит от всех сценариев компрометации. Защита определяется совокупностью прав, изоляции процессов и контроля изменений.

3.5. Резервная копия и мгновенный откат

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

Меняйте файл через SFTP, SSH или надежную панель. Подготовьте способ отката, который не зависит от работоспособности CMS. При ошибке 500 административная панель приложения тоже может стать недоступной.

Изменения .htaccess обычно применяются к последующим запросам без перезапуска Apache. Изменения основной конфигурации требуют отдельной проверки и корректной перезагрузки конфигурации.

AllowOverride, модули и наследование

Почему файл может существовать, но не работать

Apache должен разрешать распределённую конфигурацию для соответствующего каталога. Этим управляют AllowOverride и AllowOverrideList в основной конфигурации сервера, обычно внутри <Directory>. В самом .htaccess разрешить его собственную обработку нельзя.

# Основная конфигурация Apache, НЕ .htaccess
<Directory "/var/www/example/public">
    AllowOverride None
    AllowOverrideList RewriteEngine RewriteBase RewriteCond RewriteRule
    Require all granted
</Directory>
Apache

Это иллюстрация разрешения только директив перезаписи. Для реального файла CMS список может потребоваться расширить: например, из-за Options, DirectoryIndex или ErrorDocument. Наличие директивы в разрешённом списке не загружает соответствующий модуль.

AllowOverride All разрешает все категории директив, которые вообще допустимы в .htaccess, но не превращает файл в полноценную серверную конфигурацию. Это удобная, однако широкая делегация полномочий. На управляемом сервере обычно лучше явно разрешить необходимое. При AllowOverride None и AllowOverrideList None файлы распределённой конфигурации не используются.

Категории AllowOverride объединяют директивы по назначению: FileInfo включает многие настройки обработки запросов и rewrite, AuthConfig — авторизацию, Indexes — индексирование каталогов и связанные настройки, Options — серверные опции, Limit — исторические ограничения доступа. Названия категорий не заменяют проверку документации конкретной директивы. В Apache 2.4 современные Require относятся к механизму авторизации, а не к старым Order/Allow/Deny.

Для каждой директивы важны её контекст, разрешённая категория override и наличие модуля. Например, нельзя поместить в .htaccess Listen, <VirtualHost>, LoadModule или RewriteMap: они настраиваются на другом уровне.

Модули: почему одинаковые файлы ведут себя по-разному

mod_rewrite отвечает за перезапись адресов, mod_headers — за заголовки, mod_expires — за сроки кеширования, mod_deflate — за gzip-сжатие, mod_brotli — за Brotli, mod_dir — за индексные страницы и поведение каталогов. Ограничения доступа используют модули семейства mod_authz_*, парольная защита — также модули аутентификации.

Проверка модуля выглядит так:

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
</IfModule>
Apache

Если модуля нет, блок будет пропущен. Это удобно для необязательной оптимизации, но опасно для обязательной защиты: сайт может «успешно работать» без нужного ограничения. IfModule не проверяет разрешение директивы через AllowOverride и не гарантирует отсутствие ошибки 500.

Наследование — не простое склеивание файлов

Для запроса к /catalog/item/ могут участвовать правила нескольких каталогов, настройки виртуального хоста и вложенные конфигурационные секции. Конкретный результат зависит от модуля и правил слияния его настроек.

Не следует представлять это как последовательное выполнение всех .htaccess сверху вниз. В частности, правила mod_rewrite имеют собственную модель наследования; для специальных сценариев существуют RewriteOptions Inherit, InheritBefore и другие варианты. Вложенный файл с rewrite-настройками может изменить ожидаемое поведение родительского набора. Добавлять наследование вслепую тоже нельзя: это может повторно запустить маршрутизацию CMS.

Секции <Files>, <FilesMatch>, <Directory> и <Location> на серверном уровне объединяются по правилам Apache, а не только по визуальному положению в файле. В .htaccess доступны не все эти контейнеры: например, <Directory> и <Location> туда не помещают. Отдельно учитывайте слияние авторизации: вложенный Require может изменить результат родительских ограничений; директива AuthMerging управляет некоторыми аспектами этого объединения.

Практический вывод: если корневое правило не действует в одном конкретном каталоге, нужно проверить его вложенные файлы и серверную конфигурацию, а не копировать туда весь корневой .htaccess.

Options и символические ссылки

Options -Indexes -MultiViews
Apache

Здесь используются относительные изменения: отключается листинг и согласование нескольких вариантов ресурса, остальные опции не перечисляются заново. MultiViews может мешать маршрутизации CMS, сопоставляя запрос с существующим файлом до ожидаемого rewrite.

Не смешивайте в одной директиве относительную форму с +/- и абсолютный список без этих знаков. Options FollowSymLinks, например, не равнозначно Options +FollowSymLinks: первое задаёт набор опций, второе добавляет опцию к существующим.

Для работы per-directory rewrite Apache требует подходящей настройки FollowSymLinks или SymLinksIfOwnerMatch. На хостинге изменение этих параметров может быть запрещено. Не включайте произвольное следование ссылкам ради устранения ошибки без согласования модели безопасности и прав доступа.

Синтаксис и базовые директивы

Как читать конфигурацию

Обычно строка содержит имя директивы и аргументы. Блоки ограничиваются открывающим и закрывающим контейнером. Комментарии безопаснее размещать на отдельной строке, начинающейся с #: комментарий в конце строки поддерживается не так, как многие ожидают, и может стать частью аргумента.

# Сначала пробуем index.php, затем index.html
DirectoryIndex index.php index.html

# Не показываем автоматически список файлов
Options -Indexes
Apache

Имена директив Apache в целом нечувствительны к регистру, но их аргументы, пути и регулярные выражения могут быть чувствительными. Файл /Images/Logo.png на обычной Linux-файловой системе не обязан совпадать с /images/logo.png.

Кавычки нужны, когда аргумент содержит пробелы. Не используйте типографские кавычки «» или “” вместо обычных ASCII-кавычек в коде. Не добавляйте HTML-теги форматирования вокруг директив при переносе из редактора блога.

Три разных значения слова «путь»

/var/www/example/public — абсолютный путь файловой системы. /catalog/ — URL-путь от корня сайта. catalog/ в шаблоне RewriteRule внутри корневого .htaccess — строка без начального слеша, которую сопоставляет per-directory rewrite.

Универсального правила «везде писать от корня сервера» не существует. Например, AuthUserFile принимает путь к файлу паролей в файловой системе, локальный ErrorDocument — URL-путь, а поведение подстановки RewriteRule зависит от контекста и формы адреса.

Индексный файл и доступ к каталогу

DirectoryIndex определяет, какой ресурс использовать при запросе каталога. Это не то же самое, что маршрутизация всех несуществующих адресов через index.php.

Реальный каталог без завершающего слеша Apache обычно нормализует через mod_dir. Отключение DirectorySlash ради косметики URL способно создать ошибки относительных ссылок и риски раскрытия содержимого. URL физических каталогов и виртуальных страниц CMS не следует нормализовать одним слепым правилом.

Как работает mod_rewrite: от простого правила к маршрутизации CMS

Модуль mod_rewrite сопоставляет запросы с условиями и шаблонами, а затем изменяет внутренний маршрут или формирует перенаправление. Это не язык PHP и не произвольный скриптовый язык: у него собственные правила контекста, обработки и повторных проходов.

Включение механизма и структура правила

RewriteEngine On
RewriteRule ^old-page/$ /new-page/ [R=302,L]
Apache

RewriteEngine On включает механизм переписывания для соответствующего контекста. В RewriteRule первый аргумент — регулярное выражение, второй — подстановка, третий, необязательный, — флаги в квадратных скобках.

Пример перенаправляет /old-page/ на /new-page/. Для первоначальной проверки выбран временный код 302: постоянный редирект браузер может надолго закешировать. После проверки перенос постоянной страницы обычно оформляют кодом 301.

В корневом .htaccess шаблон правила видит путь без начального слеша. Поэтому используется ^old-page/$, а не ^/old-page/$. В .htaccess, расположенном в /catalog/, запрос /catalog/item/ сопоставляется с item/. При этом %{REQUEST_URI} обычно содержит полный путь запроса с начальным /, независимо от расположения файла.

Важно различать три вещи: URL-путь /catalog/item/, путь файловой системы /var/www/example/public/catalog/ и относительный путь, который видит конкретное правило. Смешение этих пространств — одна из главных причин ошибок.

Регулярные выражения без лишней магии

КонструкцияЗначениеПример
^Начало строки^catalog/
$Конец строки^about/$
.Любой отдельный символa.b
\.Буквальная точкаindex\.php
*Ноль или больше повторений.*
+Один или больше повторений[0-9]+
?Необязательность предыдущего элемента/?$
(…)Группа с запоминанием^article/([0-9]+)/$
(?:…)Группа без запоминания`^(?:news
[…]Набор символов[a-z0-9-]+
``Альтернатива

Захваченные группы RewriteRule доступны как $1, $2 и далее. Захваты из последнего совпавшего RewriteCond — как %1, %2. Это разные наборы ссылок, и смешивать их нельзя.

RewriteEngine On
RewriteRule ^article/([0-9]+)/?$ /article.php?id=$1 [END]
Apache

Запрос /article/42/ внутренне обслуживается скриптом /article.php с параметром id=42. Браузер продолжает показывать красивый адрес. Это rewrite, а не редирект: ответа с Location здесь нет.

Пример рассчитан на Apache 2.4 и приложение с таким обработчиком. В готовой CMS не стоит создавать собственный параллельный роутер без необходимости.

Условия RewriteCond и логика AND/OR

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [END]
Apache

REQUEST_FILENAME в обычном файловом контексте .htaccess — путь к предполагаемому локальному ресурсу. Проверка -f означает существующий обычный файл, -d — существующий каталог, -l — символическую ссылку. Знак ! инвертирует условие.

В примере запрос передаётся контроллеру только тогда, когда не соответствует существующему файлу и существующему каталогу. Картинки, стили и скрипты при такой схеме обычно обслуживаются напрямую. Однако файл всё ещё может оказаться недоступен из-за прав, правил доступа или другого уровня конфигурации: -f проверяет существование, а не успешную HTTP-доступность.

Несколько условий подряд по умолчанию объединяются логическим «И». Флаг [OR] связывает соответствующее условие со следующим через «ИЛИ». Группа условий относится только к непосредственно следующему RewriteRule, а не ко всем последующим правилам файла.

Флаги, которые полезно понимать

ФлагНазначениеВажное ограничение
LОстановить текущий набор правил в этом проходеНе запрещает новый проход после внутреннего перенаправления
ENDЗавершить дальнейшую per-directory rewrite-обработку запросаApache 2.4; не заменяйте им вслепую штатные правила CMS
R=301Постоянный внешний редиректМожет кешироваться; метод запроса не гарантированно сохраняется
R=302Временный внешний редиректУдобен при тестировании; не для гарантированного сохранения POST
R=307Временный редирект с сохранением методаКлиент повторяет метод и тело запроса
R=308Постоянный редирект с сохранением методаНужны совместимые клиенты и осознанная политика API
NCСопоставление без учёта регистраНе делает всю файловую систему регистронезависимой
QSAДобавить исходные параметры к параметрам подстановкиМожет создать повторяющиеся параметры
QSDОтбросить исходную строку параметровДоступен в Apache 2.4; не удаляйте параметры без разбора
FОтветить 403 ForbiddenУдобен для явного запрета
GОтветить 410 GoneТолько для действительно удалённого ресурса
E=NAME:valueУстановить переменную окруженияЕсть особенности per-directory-контекста и повторных проходов
BЭкранировать обратные ссылкиТребует понимания декодирования URL и целевой подстановки
NEНе выполнять обычное экранирование в редиректеНе является универсальным исправлением проблем с URL
PTПередать результат следующему механизму сопоставления URIВ per-directory-контексте поведение подразумевается автоматически
DPIОтбросить PATH_INFO в текущем проходеНужен лишь для определённых схем маршрутизации

Универсальное правило «добавьте [L], и циклы исчезнут» неверно. Например, переписывание /missing на /index.php может запустить новый проход, в котором обработчик снова попадает под слишком широкое правило. Нужны правильные исключения, проверки существования файла или подходящий END, а не только флаг остановки.

Query string: параметры не входят в шаблон пути

В адресе /search/?q=apache&page=2 шаблон RewriteRule сопоставляется с путём, а параметры проверяются отдельно через %{QUERY_STRING}.

Если подстановка не задаёт новую строку параметров, исходная обычно сохраняется. Если подстановка содержит собственные параметры, они обычно заменяют исходные. QSA объединяет обе строки; QSD позволяет отбросить исходную, когда подстановка своей строки не задаёт.

RewriteEngine On
RewriteRule ^article/([0-9]+)/?$ /article.php?id=$1 [QSA,END]
Apache

Запрос /article/42/?lang=ru получит параметры id=42&lang=ru. Но /article/42/?id=99 создаёт неоднозначность повторного id: результат зависит от парсера приложения. Для идентификаторов и управляющих параметров часто безопаснее не добавлять QSA, если задача этого не требует.

Фрагмент после #, например #comments, браузер вообще не отправляет серверу. Правило .htaccess не может сопоставить такой фрагмент входящего запроса.

REQUEST_URI и THE_REQUEST: как не перенаправить собственный rewrite

THE_REQUEST содержит исходную строку HTTP-запроса, например GET /index.php HTTP/1.1, и не меняется из-за внутренних переписываний. Это полезно, если нужно убрать публичный /index.php, но сохранить внутреннюю передачу управления тому же файлу.

# Только для сайта в корне; сначала проверьте поведение CMS.
RewriteEngine On
RewriteCond %{THE_REQUEST} "\s/+index\.php(?:[?\s])" [NC]
RewriteRule ^index\.php$ / [R=302,L]
Apache

В отличие от безусловного редиректа index.php, это правило реагирует на запрос клиента, а не на результат маршрутизации. После проверки можно заменить 302 на 301. Параметры сохраняются: удаление их целиком способно сломать старые ссылки и служебные сценарии.

RewriteBase, слеши и подкаталоги

RewriteBase задаёт базовый URL-путь для относительных подстановок в per-directory-контексте. Она не меняет DocumentRoot, не «включает ЧПУ» самостоятельно и нужна не каждому проекту. При подстановке /index.php путь уже абсолютный относительно URL-корня хоста.

Нельзя исправлять установку в подкаталоге только одной строкой RewriteBase: необходимо учитывать место входного файла, публичный адрес приложения, Alias, виртуальный хост и собственные настройки CMS. В конфигурации VirtualHost и в .htaccess правила имеют разный контекст; механическое копирование способно изменить смысл.

Кодирование URL и опасные универсальные правила

Пути с пробелами, кириллицей, %2F, %25, +, ? и повторным кодированием требуют отдельных тестов. mod_rewrite работает с декодированным представлением пути на определённых этапах, тогда как THE_REQUEST позволяет видеть исходное представление запроса. Поведение закодированных разделителей зависит также от серверной настройки AllowEncodedSlashes, которую не задают произвольно в .htaccess.

Не вставляйте пользовательский путь или параметр в целевой URL без понимания экранирования. Не включайте NE, B и другие флаги методом перебора. Обновления безопасности Apache могут ужесточать обработку опасных подстановок: правильный выход — уточнить правило по документации установленной версии, а не включать разрешающие обходные флаги ради исчезновения ошибки.

Редиректы, HTTPS и канонические адреса

Простой перенос страницы

Для одного переноса удобен RedirectMatch из mod_alias:

RedirectMatch 302 ^/old-page/?$ /new-page/
Apache

Здесь начальный / нужен: синтаксис сопоставления отличается от RewriteRule в .htaccess. У обычного Redirect сопоставление пути префиксное: правило для /old может затронуть и дочерние адреса. Когда требуется точное совпадение, выбирайте якоря регулярного выражения.

В файле с развитой маршрутизацией проще держать редиректы в одном механизме mod_rewrite. Порядок директив разных модулей не сводится к чтению файла сверху вниз: смешивание Redirect и RewriteRule может дать неожиданный результат.

HTTPS и единый домен одним переходом

Ниже пример только для схемы, где Apache сам принимает TLS и корректно видит HTTPS. Он предполагает основной адрес https://example.com, доступность сертификатов на всех принимаемых HTTPS-именах и отдельную настройку допустимых хостов на сервере.

RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=302,L]
Apache

Правило ставят до внутренней маршрутизации CMS. Оно объединяет смену схемы и имени хоста в один редирект. Фиксированный домен предпочтительнее подстановки непроверенного %{HTTP_HOST}: заголовок Host приходит от клиента.

После тестов обычных страниц переход можно сделать постоянным. Для POST, API, загрузок и вебхуков решение принимается отдельно: некоторые клиенты не следуют редиректам, а 301/302 могут привести к смене метода. Лучше сразу настроить интеграции на правильный HTTPS-адрес, чем лечить их общей переадресацией.

Редирект не исправляет недействительный сертификат: TLS-соединение устанавливается до получения HTTP-ответа. Чтобы перенаправлять https://www.example.com, сертификат должен подходить и этому имени.

HTTPS за reverse proxy или CDN

Если TLS завершается на Nginx, балансировщике или CDN, Apache может получать обычный HTTP. Тогда %{HTTPS} остаётся off, даже когда пользователь уже открыл HTTPS. Результат наивного правила — бесконечный редирект на тот же адрес.

Надёжное решение — согласовать схему на доверенном пограничном сервере, ограничить прямой доступ к origin и передавать приложению корректные признаки исходного HTTPS. Проверка X-Forwarded-Proto имеет смысл только тогда, когда доверенный прокси перезаписывает этот заголовок, а клиент не может подставить его напрямую. Однострочный рецепт, доверяющий любому входящему заголовку, небезопасен.

Аналогично устроено восстановление IP клиента: корректный mod_remoteip и список доверенных прокси на сервере лучше, чем проверка произвольного X-Forwarded-For в .htaccess.

Завершающий слеш, регистр и старые URL

У реальных каталогов добавлением завершающего / обычно занимается mod_dir через DirectorySlash. У виртуальных URL формат выбирает CMS. Глобальное добавление или удаление слеша может нарушить API, ссылки на файлы и маршрутизацию.

Регистронезависимый матчинг [NC] не преобразует адрес в нижний регистр. Универсального безопасного однострочного преобразования всех URL для любого .htaccess нет. При сложной нормализации разумнее использовать приложение или основной конфиг сервера.

Перенос старого сайта требует карты соответствий: /old-product/ должен вести на соответствующий товар, а не всё подряд на главную. Массовое перенаправление исчезнувших страниц на главную ухудшает пользовательский опыт и может восприниматься поисковой системой как soft 404.

Порядок важнее количества правил

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

Отдельно проверяйте .well-known/acme-challenge/ для подтверждения сертификатов, верификационные файлы, вебхуки, платёжные callback-адреса и обмены с внешними системами. Не добавляйте исключения наугад: сначала выясните, какие запросы должны проходить без перенаправлений и дополнительной авторизации.

Защита файлов и ограничение доступа

Запрет просмотра содержимого каталога

Если пользователь открыл каталог без индексного файла, Apache при включенной опции Indexes может показать список файлов. Чтобы запретить такой листинг:

Options -Indexes
Apache

Это не закрывает сами файлы. Если посетитель знает адрес /backup/database.sql, запрет листинга не мешает скачать файл. Резервные копии, дампы, ключи, экспорт персональных данных и журналы нужно хранить вне публичного каталога либо защищать независимо.

Защита отдельных служебных файлов

Для Apache 2.4 применяют современный синтаксис авторизации:

<FilesMatch "(?i)^(?:\.htaccess|\.htpasswd|\.env(?:\..*)?|composer\.(?:json|lock))$">
    Require all denied
</FilesMatch>
Apache

Этот пример запрещает HTTP-доступ к перечисленным именам в области действия конфигурации. Он не мешает PHP читать нужные файлы на диске. Список адаптируют к проекту, а защиту проверяют фактическим HTTP-запросом.

В стандартных конфигурациях Apache часто уже есть защита файлов с именем .ht..., но рассчитывать на нее без проверки нельзя. Если запрос обрабатывает Nginx, Apache-правило может вообще не участвовать.

Для резервных копий можно добавить отдельный запрет:

<FilesMatch "(?i)\.(?:sql|bak|old|orig|swp)$">
    Require all denied
</FilesMatch>
Apache

Не запрещайте все .zip или .json без анализа: сайт может законно раздавать архивы, JSON-манифесты и API-ресурсы. Правила по расширениям — дополнительный барьер, а не замена правильному размещению секретов.

Закрытые каталоги и скрытые пути

Если каталог полностью приватный, в его собственном .htaccess можно использовать:

Require all denied
Apache

Это подходит, например, для отдельного каталога с внутренними выгрузками, который не должен обслуживаться по HTTP. Файловые операции приложения продолжат зависеть от прав ОС, а не от этой директивы.

Закрыть .git и другие скрытые пути с помощью mod_rewrite можно так, поместив правило перед маршрутизатором CMS:

RewriteEngine On
RewriteRule (^|/)\.(?!well-known(?:/|$)) - [F]
Apache

Правило ищет сегмент пути, начинающийся с точки; .well-known оставлено исключением для стандартных HTTP-механизмов. Оно не превращает весь каталог .well-known в безопасный: публикуйте там только нужное и запещайте исполнение загружаемого кода. Внешний Nginx/CDN должен иметь соответствующие ограничения. Надежнее вообще не выкладывать .git и секреты в DocumentRoot.

Ограничение доступа по IP

<RequireAny>
    Require ip 192.0.2.10
    Require ip 198.51.100.0/24
    Require ip 2001:db8::/32
</RequireAny>
Apache

Адреса здесь демонстрационные: замените их своими. Доступ получит клиент, удовлетворяющий хотя бы одному условию.

За обратным прокси Apache может видеть IP прокси, а не посетителя. Доверенные прокси и восстановление адреса настраивают на уровне сервера, например через mod_remoteip. Нельзя считать произвольный X-Forwarded-For доказательством адреса клиента: без границы доверия его легко подделать.

IP-фильтр неудобен для пользователей с меняющимся адресом, мобильным интернетом и IPv6. Для административного доступа зачастую лучше VPN или шлюз доступа с аутентификацией.

Пароль на тестовый сайт

AuthType Basic
AuthName "Private staging"
AuthUserFile /srv/secrets/staging.htpasswd
Require valid-user
Apache

AuthUserFile — абсолютный путь в файловой системе сервера, не URL. Файл паролей нужно хранить вне публичного каталога и сделать читаемым серверу без избыточных прав.

При наличии утилиты htpasswd файл создают так:

htpasswd -cB /srv/secrets/staging.htpasswd editor
Bash

Ключ -c создает новый файл и может перезаписать существующий. Для добавления следующего пользователя его убирают:

htpasswd -B /srv/secrets/staging.htpasswd reviewer
Bash

Basic Auth обязательно используют по HTTPS: сама схема не шифрует пароль. Она также влияет на роботов, вебхуки, фоновые HTTP-запросы CMS и внешние интеграции. Если приложение само использует заголовок Authorization, дополнительный слой Basic Auth на том же адресе может конфликтовать с API-аутентификацией.

Для закрытого стенда пароль полезнее одного robots.txt: запрет обхода не равен запрету доступа. noindex помогает управлять индексацией, но также не защищает данные.

IP и пароль одновременно

AuthType Basic
AuthName "Restricted area"
AuthUserFile /srv/secrets/admin.htpasswd

<RequireAll>
    Require ip 192.0.2.10
    Require valid-user
</RequireAll>
Apache

RequireAll требует выполнения обоих условий. Замена на RequireAny разрешит доступ либо по IP, либо по паролю — это уже другая политика безопасности.

Старые конструкции Order, Allow, Deny, Satisfy относятся к прежней модели контроля доступа. В Apache 2.4 они могут работать через модуль совместимости, но смешивание двух моделей делает конфигурацию трудно предсказуемой. Новые правила лучше писать через Require.

Запрет исполнения PHP в загрузках

Каталог пользовательских загрузок должен принимать данные, а не исполняемый код. Один из дополнительных барьеров — отдельный .htaccess в таком каталоге:

<FilesMatch "(?i)\.(?:php[0-9]*|phtml|pht|phar)(?:\.|$)">
    Require all denied
</FilesMatch>
Apache

Он запрещает HTTP-доступ к подходящим именам, включая некоторые варианты двойных расширений. Однако полный перечень исполняемых расширений зависит от обработчиков сервера. Это не универсальная защита от любого возможного исполнения.

Самая надежная архитектура — хранить загрузки вне исполняемого дерева либо в отдельном хранилище/виртуальном хосте без PHP-обработчика. На уровне приложения нужны проверка допустимых форматов, безопасные имена, ограничения размеров и запрет загрузки .htaccess, .user.ini и других управляющих файлов. Если злоумышленник может заменить защитный .htaccess, барьер теряет смысл.

Не используйте бездумно RemoveHandler или php_flag engine off: в некоторых конфигурациях это способно привести к выдаче исходного PHP как текста. Запрет доступа надежнее попытки «отключить PHP» неизвестным способом, но окончательную политику нужно задавать на уровне сервера.

Чего не стоит ожидать от блокировок ботов и Referer

Заголовки User-Agent и Referer подделываются. Блокировка по ним может уменьшить часть нежелательных обращений, но не заменяет WAF, лимиты запросов, защиту учетных записей и обновления приложения.

Защита от хотлинков по Referer нередко ломает картинки в почте, RSS, приложениях и браузерах с усиленной приватностью. Для приватных файлов нужны авторизация, короткоживущие подписанные URL и правильно организованная выдача, а не проверка источника перехода.

Заголовки, MIME-типы и политика браузера

Как работает Header

Директива Header относится к mod_headers. Например:

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
Apache

nosniff ограничивает попытки браузера интерпретировать ресурс не в соответствии с объявленным типом. Он особенно важен при загрузке пользовательских файлов, но может выявить ошибочные MIME-типы CSS и JavaScript.

Referrer-Policy регулирует передачу адреса исходной страницы при переходах и загрузке ресурсов. Политику выбирают с учетом аналитики и приватности.

always — не просто «повторить настройку для надежности»: Apache использует разные внутренние таблицы заголовков. Ответы CGI/FastCGI, прокси и ошибки могут проходить иначе, чем обычная статика. Одновременная установка заголовка приложением и сервером иногда дает дубликаты. Если конкретный заголовок решено централизованно контролировать в Apache, может понадобиться убрать его из обычной таблицы и установить в таблице always:

Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
Apache

Проверяйте результат на ответах 200, 301, 403, 404 и 500. Отсутствие модуля внутри <IfModule> тихо отключит весь блок; для обязательной политики это нужно обнаруживать мониторингом.

HSTS

Strict-Transport-Security сообщает браузеру, что сайт должен открываться только по HTTPS. Это не установка сертификата и не первый HTTP→HTTPS-редирект.

На сервере, где TLS завершается непосредственно в Apache, пример ограниченного включения:

Header always set Strict-Transport-Security "max-age=300" "expr=%{HTTPS} == 'on'"
Apache

Сначала проверяют HTTPS на всех нужных адресах с небольшим сроком. После проверки срок можно увеличивать. Если TLS завершается на прокси, заголовок обычно удобнее и надежнее выставлять там.

includeSubDomains распространяет политику на поддомены, а preload связан с отдельным механизмом предварительных списков браузеров. Их не добавляют «на всякий случай»: неподготовленный поддомен может перестать открываться, а отмена политики не мгновенна. HSTS тестируют отдельно от обычных редиректов.

CSP и защита от встраивания

Content Security Policy ограничивает источники скриптов, стилей, фреймов и других ресурсов. Универсальной CSP для WordPress, Битрикс и всех плагинов не существует. Строгая политика без аудита способна отключить редактор, аналитику, карты и оплату.

Часто начинают с Content-Security-Policy-Report-Only, изучают нарушения и лишь затем вводят блокировку. Nonce для скриптов должен быть непредсказуемым и формироваться динамически; постоянное значение в .htaccess не обеспечивает нужной защиты.

Для запрета чужого встраивания используют CSP frame-ancestors; X-Frame-Options может быть дополнительным совместимым механизмом. Учитывайте легитимные виджеты, предпросмотр и встраивание админки. Не выдавайте несколько независимых CSP в надежде, что последняя заменит предыдущую: браузер применяет политики совместно.

CORS

CORS регулирует возможность JavaScript читать ответы другого origin. Это не запрет сетевого доступа и не замена аутентификации. Origin включает схему, имя хоста и порт.

Access-Control-Allow-Origin: * допустим для действительно публичных ресурсов без credential-сценария. Для запросов с учетными данными нужен разрешенный конкретный origin и согласованная политика credentials. Нельзя без проверки отражать любой присланный Origin.

При динамическом выборе origin учитывают Vary: Origin и поведение кеша. Предварительный запрос OPTIONS должен обрабатываться корректно. API-политику часто лучше задавать в приложении или API-шлюзе, а не одним глобальным заголовком для всего сайта.

MIME и кодировка

Для статических ресурсов иногда требуются явные типы:

AddType image/webp .webp
AddType image/avif .avif
AddType font/woff2 .woff2
Apache

Сначала проверьте фактический ответ: современные конфигурации обычно уже знают эти типы. AddDefaultCharset UTF-8 может задать значение по умолчанию для определенных текстовых ответов, но не перекодирует байты файлов и не исправляет кодировку базы данных. Смешанный сайт с разными кодировками нельзя чинить одной директивой.

Чтобы заставить скачивать конкретный файл, лучше назначить Content-Disposition: attachment в узкой области, сохранив корректный MIME-тип. Глобально превращать все PDF или изображения в application/octet-stream обычно не требуется.

Кеширование и сжатие: что действительно ускоряется

Кеш браузера не равен кешу CMS

Кеш браузера хранит ответы на устройстве посетителя. CDN хранит их на внешних узлах. WordPress-плагин или Битрикс может кешировать HTML, результаты компонентов и запросов. PHP OPcache хранит скомпилированный PHP-код. Это разные уровни с разными правилами инвалидирования.

.htaccess может влиять на HTTP-заголовки, сжатие и выдачу готовой статики, но сам не ускоряет SQL-запросы и не исправляет тяжелый PHP-код.

Умеренное кеширование статики

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 day"
    ExpiresByType application/javascript "access plus 1 day"
    ExpiresByType text/javascript "access plus 1 day"
    ExpiresByType image/jpeg "access plus 7 days"
    ExpiresByType image/png "access plus 7 days"
    ExpiresByType image/webp "access plus 7 days"
    ExpiresByType image/avif "access plus 7 days"
    ExpiresByType font/woff2 "access plus 30 days"
</IfModule>
Apache

Это пример, не обязательные сроки. mod_expires формирует срок свежести через Expires и Cache-Control: max-age. Не добавляйте другой глобальный Cache-Control поверх него, не проверив итоговые заголовки.

Годовой кеш с immutable хорош для файлов, имя которых меняется при каждом изменении содержимого, например app.8f2a1c.css. Для файла style.css, перезаписываемого по тому же URL, такой режим может надолго оставить старую версию у посетителей. Версионирование через query string также требует проверки того, как конкретный CDN включает параметры в ключ кеша.

Какие ответы нельзя кешировать как публичные

Корзина, оформление заказа, профиль, административная панель и персонализированные API-ответы не должны попадать в общий кеш без специальной безопасной схемы. Наличие cookies или Set-Cookie не является универсальной гарантией обхода любого CDN-кеша.

private запрещает хранение в общих кешах, но допускает браузерный. no-store запрещает хранение. no-cache означает необходимость проверки перед повторным использованием, а не абсолютный запрет сохранения. Эти различия важны для персональных данных.

Политику персонализированных страниц лучше формировать в приложении, где известны пользователь и содержимое ответа. Нельзя одним ExpiresDefault объявлять все страницы интернет-магазина публичными на месяц.

ETag, Last-Modified и 304

ETag и Last-Modified позволяют клиенту проверить, изменился ли ресурс. При отсутствии изменений сервер может вернуть 304 Not Modified без тела ответа.

Рекомендация «всегда отключайте ETag» слишком груба. В кластере нужны согласованные валидаторы, но решение зависит от файловой системы, способа развертывания и CDN. Отключение обоих валидаторов без причины иногда увеличивает объем повторных загрузок.

Сжатие текстовых ресурсов

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css
    AddOutputFilterByType DEFLATE application/javascript text/javascript
    AddOutputFilterByType DEFLATE application/json application/xml image/svg+xml
</IfModule>
Apache

Gzip обычно полезен для текста. JPEG, WebP, AVIF, ZIP и WOFF2 уже сжаты; повторное сжатие чаще тратит процессор без заметного выигрыша. Brotli можно настроить при наличии соответствующего модуля, но не стоит одновременно навешивать несколько фильтров на один ответ без понимания цепочки.

Проверьте Content-Encoding, Vary: Accept-Encoding, поведение CDN и отсутствие двойного сжатия. Vary нельзя бездумно перезаписывать: там могут быть другие существенные измерения кеша. Для чувствительных динамических ответов учитывают также риски утечек через сжатие и модель угроз приложения.

Если статику отдает Nginx, сжатие и заголовки этой статики настраиваются там. Исправление .htaccess в таком случае не ускорит изображения ни на миллисекунду.

Ошибки, параметры PHP и режим обслуживания

Собственная страница 404

ErrorDocument 404 /errors/404.html
Apache

Путь должен существовать и быть доступен без повторной ошибки. Локальный обработчик позволяет сохранить ответ об ошибке; внешний URL в ErrorDocument приводит к перенаправлению и меняет семантику ответа.

Различайте ошибку Apache и ошибку приложения. Когда rewrite направил запрос в index.php, сервер нашёл исполняемый файл. Теперь CMS должна сама определить отсутствие материала и вернуть статус 404. Один только ErrorDocument не заставит CMS перестать отдавать код 200 для несуществующей статьи.

Для PHP-обработчика статус обычно задают явно:

<?php
http_response_code(404);
header('Content-Type: text/html; charset=UTF-8');
// Здесь выводится шаблон ошибки.
PHP

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

PHP: mod_php, CGI и PHP-FPM

Директивы php_value и php_flag в .htaccess относятся к интеграции PHP как модуля Apache. Для PHP-FPM это не универсальный способ управления настройками и часто причина ошибки 500.

При CGI/FastCGI часть разрешённых PHP-настроек может задаваться через .user.ini, если этот механизм включён. Другие параметры меняют в php.ini, конфигурации пула FPM или панели хостинга. Не все параметры разрешено менять на уровне каталога, а настройки администратора могут иметь более высокий приоритет. .user.ini имеет собственное кеширование: его изменения не обязаны вступать в силу немедленно.

Повышение upload_max_filesize не гарантирует загрузку большого файла. Нужно учитывать post_max_size, память приложения, ограничения CMS, тайм-ауты PHP и прокси, лимиты тела запроса Apache/Nginx/CDN. Размер тела multipart-запроса больше самого загружаемого файла.

На рабочем сайте сообщения PHP обычно записывают в закрытый журнал, а не показывают посетителю. Публичный phpinfo() раскрывает конфигурацию; если его временно использовали для диагностики, доступ нужно ограничить, а сам файл удалить.

Режим обслуживания с корректным 503

Для коротких технических работ подходит код 503 Service Unavailable, а не постоянный редирект 301. Пример ниже предназначен для корневого .htaccess, ставится до маршрутизации CMS и требует существующего самодостаточного файла /maintenance.html:

ErrorDocument 503 /maintenance.html
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^ - [R=503,L]
Apache

Несмотря на имя флага R, код вне диапазона перенаправлений в таком правиле используется для возврата соответствующего HTTP-статуса, а не перехода на другой URL. Исключение для страницы обслуживания предотвращает повторный отказ при внутреннем запросе к ней. Чтобы не открывать дополнительные пути, стили можно поместить внутрь HTML.

Пример временно закрывает и API, и административные URL. При необходимости исключения проектируют отдельно; клиентские IP за прокси сначала должны корректно определяться на сервере. Retry-After с разумным временем ожидания можно добавить на уровне обработчика или конфигурации ответов 503, но нельзя безусловно отправлять его на все нормальные ответы сайта.

Если в проекте есть штатный режим обслуживания CMS, часто разумнее использовать его. Но при недоступном PHP или базе данных статическая страница на внешнем сервере надёжнее. Заранее определите, какие операции действительно можно остановить: например, уведомления об уже оплаченных заказах нельзя случайно потерять.

WordPress: как устроен .htaccess и что разрешено менять

Зачем он нужен WordPress

На Apache файл прежде всего обеспечивает работу «красивых» постоянных ссылок. Посетитель открывает /blog/chto-takoe-htaccess/, хотя такого каталога на диске нет. Веб-сервер направляет запрос в index.php, а WordPress по своим внутренним правилам определяет запись, страницу, архив или другой объект.

Здесь работают два разных уровня маршрутизации. Apache отвечает за доставку запроса в WordPress. WordPress сопоставляет URL со своими правилами Rewrite API и параметрами запроса. Изменение .htaccess не исправит ошибочно зарегистрированный тип записей, конфликт slug или неправильно добавленное правило плагина.

На сервере без Apache постоянные ссылки тоже работают: необходимую маршрутизацию выполняет Nginx, IIS или другой совместимый сервер. Сам файл .htaccess не является обязательной частью любого WordPress-сайта.

Базовый блок для обычного сайта в корне домена

Для одиночной установки, доступной непосредственно по https://example.com/, официальный справочник WordPress по Apache и .htaccess приводит следующий базовый набор правил:

# BEGIN WordPress
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Apache

Это базовый блок маршрутизации, а не полный эталон для любого проекта. Конкретный WordPress может сгенерировать дополнительные комментарии, обёртку <IfModule mod_rewrite.c> или иные правила с учётом размещения. Плагины кеширования, безопасности и мультиязычности тоже добавляют свои секции.

RewriteEngine On включает механизм переписывания в данном контексте.

RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] сохраняет значение заголовка Authorization в переменной окружения. Подстановка - означает «не менять путь». Это важно для некоторых вариантов передачи HTTP-авторизации в PHP, в том числе для API. Правило не проверяет пароль, не предоставляет доступ и не заменяет настройку FastCGI или прокси.

RewriteBase / задаёт базовый URL для относительных подстановок в соответствующих сценариях. Это не файловый путь и не универсальная команда «установить корень сайта».

RewriteRule ^index\.php$ - [L] прекращает текущий проход правил для самого входного файла. Экранированная точка означает буквально точку. Это один из элементов предотвращения повторной ненужной маршрутизации.

Условия !-f и !-d пропускают существующие файлы и каталоги: например, изображение из wp-content/uploads не должно по этому правилу превращаться в запрос к WordPress.

RewriteRule . /index.php [L] направляет остальные непустые пути во входной скрипт. В адресной строке остаётся исходный URL: это внутреннее переписывание, а не редирект. Главную страницу при запросе каталога обычно обеспечивает также механизм DirectoryIndex.

Нельзя бездумно заменять этот блок на внешне похожий фрагмент для другой CMS. WordPress ожидает собственную точку входа и собственный процесс определения маршрута.

Что означают BEGIN WordPress и END WordPress

Это комментарии Apache, но для WordPress они обозначают автоматически управляемую область. Когда система обновляет правила, содержимое между маркерами может быть перезаписано.

Собственные перенаправления размещайте вне этой области. Если перенаправление должно сработать до передачи запроса в CMS, располагайте его выше блока WordPress. Настройки заголовков и доступа размещайте исходя из их контекста: правило «всё обязательно сверху» к ним неприменимо.

Пример структуры, а не готовый файл для копирования:

# PROJECT: собственные правила, управляются вручную
RewriteEngine On
RewriteRule ^old-article/?$ https://example.com/new-article/ [R=302,L]

# Далее — блоки плагинов в порядке, который требуют эти плагины

# BEGIN WordPress
# Здесь находится реальный блок, сформированный вашей установкой
# END WordPress

# PROJECT: дополнительные настройки, если их контекст здесь уместен
Apache

Не заменяйте рабочий блок последним примером: комментарии в нём намеренно показывают только расположение секций.

Как WordPress создаёт и обновляет файл

В административной панели откройте «Настройки → Постоянные ссылки». Сохранение настроек обычно инициирует обновление правил. Если сервер и права позволяют, WordPress записывает нужный блок. Если запись недоступна, панель может предложить скопировать правила вручную.

Отсутствие файла не всегда является ошибкой: сайт может работать на Nginx, использовать центральную конфигурацию Apache или обходиться обычными ссылками вида ?p=123.

Не выдавайте права 777, чтобы заставить CMS записывать файл. Лучше выяснить владельца, группу и режим работы PHP, затем выбрать минимально необходимые разрешения. Возможность PHP изменять .htaccess удобна, но при компрометации приложения позволяет изменять и серверное поведение. В управляемой инфраструктуре файл нередко развёртывают через систему контроля версий и запрещают запись из приложения.

WordPress в подкаталоге: два разных случая

Первый случай: и файлы, и публичный сайт расположены в /blog/. В .htaccess внутри /blog/ базовый блок будет учитывать эту базу:

# BEGIN WordPress
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
# END WordPress
Apache

В шаблонах RewriteRule по-прежнему нет начального /blog/: текущий каталог уже вычтен при сопоставлении. А подстановка /blog/index.php — URL-путь от корня сайта.

Второй случай: ядро находится в /wordpress/, но публичный сайт открывается из /. Это специальная схема размещения. Нельзя просто заменить все / на /wordpress/. Нужны согласованные адреса WordPress и сайта, правильный корневой index.php, его подключение к ядру и правила в публичном корне. Используйте правила, полученные для такой установки, а не блок для публичного /blog/.

Также учитывайте, что родительский .htaccess может перехватывать запросы до подкаталога. Если в корне другая CMS, для вложенного WordPress может потребоваться явное исключение из её маршрутизации.

Multisite: почему обычного блока недостаточно

В сети WordPress нужно различать сайты по подкаталогам или доменам, обрабатывать административные URL и правильно находить общие файлы ядра. Обычный блок одиночной установки не покрывает эти задачи.

Получайте правила из экрана настройки сети именно вашей установки. В официальной документации приведены отдельные варианты для сетей с подкаталогами и поддоменами, а также исторические варианты для старых сетей. Это не взаимозаменяемые шаблоны.

Домены и поддомены требуют ещё DNS, сертификатов, конфигурации виртуальных хостов и корректного сопоставления сайтов внутри сети. .htaccess не создаёт DNS-запись и не выпускает сертификат. Глобальный редирект всех доменов на один способен разрушить доменное сопоставление Multisite.

Плагины кеширования, безопасности и SEO

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

Плагин безопасности может добавлять запреты доступа, ограничения методов и правила обработки файлов. SEO-плагин может управлять редиректами в PHP, вообще не изменяя .htaccess. Не считайте все SEO-настройки автоматически серверными.

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

Для WooCommerce и других магазинов особенно опасен общий HTML-кеш. Корзина, оформление заказа, личный кабинет, персональные цены и запросы с пользовательскими cookies требуют специальных исключений. «Кешировать всё на час» — не ускорение, если пользователи начинают видеть чужие данные.

REST API, XML-RPC, AJAX и Application Passwords

Красивые REST-адреса /wp-json/... используют маршрутизацию WordPress. Если обычные записи и REST одновременно получают серверный 404, сначала проверьте правила. Если endpoint работает через ?rest_route=/..., но не через /wp-json/..., это полезный признак проблемы с красивой маршрутизацией, хотя не окончательный диагноз.

Application Passwords используют HTTP-авторизацию и требуют сохранения соответствующего заголовка на всём пути до приложения. Дополнительная Basic Auth перед всем сайтом способна конфликтовать с ними: оба механизма рассчитывают использовать Authorization.

wp-admin/admin-ajax.php обслуживает не только административную панель. Его могут вызывать формы, фильтры товаров и другие функции публичного сайта. Закрытие всего /wp-admin/ по IP без анализа ломает такие функции.

xmlrpc.php не нужен каждому сайту, но может использоваться интеграциями. Отключайте его после проверки зависимостей, а не потому, что он присутствует в случайной «усиленной» конфигурации. Аналогично не блокируйте целиком REST API: он нужен редактору и множеству плагинов.

Защита wp-config.php и загрузок

Дополнительный запрет HTTP-доступа к конфигурации:

<Files "wp-config.php">
    Require all denied
</Files>
Apache

Нормально работающий PHP не отдаёт исходный код этого файла. Запрет — дополнительный барьер, а не замена исправной конфигурации обработчика PHP. Резервные копии wp-config.php.bak, архивы и дампы нужно защищать отдельно и прежде всего хранить вне публичного каталога.

В wp-content/uploads/.htaccess можно запретить доступ к типичным исполняемым расширениям:

<FilesMatch "(?i)\.(?:php[0-9]*|phtml|phar)(?:\.|$)">
    Require all denied
</FilesMatch>
Apache

Это иллюстрация дополнительной защиты. Реальный набор исполняемых расширений определяется сервером. Надёжнее запретить обработчик скриптов для каталога загрузок в конфигурации веб-сервера и обеспечить то же ограничение на всех фронтендах. Если злоумышленник может записать в uploads собственный .htaccess, защита, основанная только на доступном ему файле, ненадёжна.

Не закрывайте целиком wp-content: там находятся публичные стили, скрипты и изображения. Не копируйте без проверки комплексные запреты для wp-includes: плагины и разные схемы установки имеют свои зависимости.

Когда после смены ссылок появляются 404

Сначала проверьте, открывается ли прямой существующий файл. Затем сравните главную, запись, страницу, архив, REST endpoint и несуществующий URL. Если статика работает, главная открывается, а все красивые адреса нет, вероятны неработающий mod_rewrite, игнорируемый .htaccess, неверная база или ошибочная серверная маршрутизация.

Если не работает только один тип записей, проверьте регистрацию типа и его rewrite, конфликты slug и внутренние правила WordPress. Однократное сохранение постоянных ссылок может обновить их, но flush_rewrite_rules() на каждом запросе — плохая практика: это лишняя нагрузка, а при жёстком сбросе ещё и возможная запись файлов. Сброс обычно привязывают к активации, деактивации или изменению настроек, когда нужные типы и правила уже зарегистрированы.

Если изменения не видны, проверяйте отдельно кеш плагина, серверный кеш, CDN и браузер. Удаление .htaccess на рабочем сайте — не универсальный диагностический приём: одновременно можно снять ограничения доступа и нарушить служебные маршруты.

1С-Битрикс: подробный разбор .htaccess

Область применения: «Управление сайтом», коробочные продукты и облачные сервисы

Речь в этом разделе идёт прежде всего о самостоятельно размещаемом сайте на «1С-Битрикс: Управление сайтом» и об окружении Bitrix Framework. Для коробочных продуктов необходимо учитывать собственную структуру и документацию конкретной установки. Пользователь облачного Битрикс24 не получает таким способом доступ к конфигурации серверов сервиса: добавить .htaccess в облачный интерфейс и изменить работу инфраструктуры нельзя.

В Битрикс важно разделять четыре уровня: конфигурацию веб-сервера, маршрутизацию запросов в PHP, права доступа самой CMS и кеширование. Файлы .htaccess, /urlrewrite.php, .access.php и настройки компонентов относятся к разным уровням. Они не заменяют друг друга.

Где находится файл и почему одного корневого .htaccess недостаточно

Основной файл обычно расположен в корне публичной части сайта, рядом с index.php, каталогами bitrix, upload и, во многих проектах, local. Однако дополнительные .htaccess могут находиться внутри служебных директорий. Они способны ограничивать доступ, менять обработку файлов или влиять на наследование правил.

Перед переносом или восстановлением необходимо сохранить все такие файлы, включая скрытые. Нельзя скопировать только корневой .htaccess, а затем считать серверную конфигурацию проекта восстановленной. Для диагностики конкретного URL следует смотреть всю цепочку каталогов и соответствующие настройки Apache, а также конфигурацию Nginx, если он стоит перед Apache.

Типичный механизм маршрутизации

В официальном уроке 1С-Битрикс об использовании .htaccess приведён демонстрационный файл, который направляет запросы к отсутствующим физическим объектам в /bitrix/urlrewrite.php. Сам урок содержит исторические блоки для PHP 5 и PHP 7; его нельзя воспринимать как универсальный готовый конфиг для любого современного окружения.

Ниже — учебный фрагмент характерной схемы, а не полная замена файла вашего проекта:

Options -Indexes
ErrorDocument 404 /404.php
DirectoryIndex index.php index.html

<IfModule mod_rewrite.c>
    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]

    RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
</IfModule>
Apache

Здесь сохранена последовательность характерных правил из документации. Допустимость Options, доступность mod_rewrite и передача авторизации требуют проверки на конкретном сервере. В демонстрационном файле также встречается Options +FollowSymLinks: возможность следования по символическим ссылкам регулирует администратор. Если настройка запрещена хостингом, добавление строки может вызвать ошибку 500. Не включайте её вопреки политике изоляции сайтов.

Что делает каждая строка

Options -Indexes запрещает автоматическое формирование списка файлов, если у каталога нет подходящего индексного файла. Это не запрещает скачивание известного файла по прямому URL.

ErrorDocument 404 /404.php задаёт локальный обработчик ошибки 404. Файл должен существовать, а его код не должен превращать ошибку в успешный ответ. Важно: если PHP-приложение само обработало URL и вернуло страницу, Apache не обязан дополнительно запускать ErrorDocument. Ошибки, сформированные приложением, и ошибки веб-сервера — разные пути обработки.

DirectoryIndex index.php index.html задаёт порядок поиска индексных файлов при обращении к физическому каталогу. Например, /contacts/ может обслуживаться непосредственно /contacts/index.php, без перехода в общий обработчик ЧПУ.

!-f означает, что запрос не соответствует существующему обычному файлу. Благодаря этому картинки, CSS и реальные PHP-скрипты не направляются без необходимости в обработчик ЧПУ.

!-l исключает символическую ссылку. Это отдельная проверка, не означающая разрешения на произвольные ссылки и не отменяющая ограничения сервера.

!-d исключает существующий каталог. Для него дальнейшее поведение зависит, в частности, от DirectoryIndex и mod_dir.

Условие с /bitrix/urlrewrite.php$ дополнительно исключает сам обработчик. Следующее правило выполняет внутреннее переписывание URL: адрес в браузере не меняется.

Правило с REMOTE_USER предназначено для передачи заголовка Authorization через переменную окружения. Оно не проверяет пароль и само по себе не реализует авторизацию. Положение после правила с [L] означает, что выполнение зависит от проходов переписывания и конкретного пути запроса. Поэтому при проблемах обмена надо проверять фактические переменные PHP, а не считать наличие этой строки доказательством исправности авторизации.

Обёртка <IfModule> предотвращает ошибку неизвестных rewrite-директив при отсутствии модуля, но одновременно позволяет маршрутизации молча перестать работать. Для обязательного модуля правильнее проверка окружения и мониторинг, чем надежда на условную секцию.

Чем отличаются /bitrix/urlrewrite.php и /urlrewrite.php

/bitrix/urlrewrite.php — обработчик, который запускается веб-сервером в классической схеме ЧПУ. Корневой /urlrewrite.php — файл правил маршрутизации, традиционно содержащий массив $arUrlRewrite. Не стоит вручную менять файл ядра /bitrix/urlrewrite.php, чтобы добавить редирект или исправить путь каталога.

Упрощённый пример записи в корневом файле:

<?php
$arUrlRewrite = [
    [
        'CONDITION' => '#^/catalog/#',
        'RULE' => '',
        'ID' => 'bitrix:catalog',
        'PATH' => '/catalog/index.php',
        'SORT' => 100,
    ],
];
PHP

Это иллюстрация одной записи, а не инструкция перезаписать существующий файл. Реальный массив содержит другие маршруты, а порядок сопоставления пересекающихся условий важен.

При запросе /catalog/shoes/model-a/ Apache может направить обработку в /bitrix/urlrewrite.php, а правила CMS — в /catalog/index.php. Затем комплексный компонент разбирает оставшуюся часть URL и определяет раздел или товар.

Поэтому редактирование .htaccess не исправит неправильный SEF_FOLDER, неверный шаблон детальной страницы, конфликт условий в $arUrlRewrite или отсутствие нужной записи в базе. Apache отвечает за доставку запроса приложению, а не за поиск товара по символьному коду.

ЧПУ компонентов и реальная структура каталогов

В классических комплексных компонентах важны включённый режим ЧПУ, каталог ЧПУ и шаблоны адресов. Например, базовый каталог /catalog/ и шаблон #SECTION_CODE_PATH#/#ELEMENT_CODE#/ должны соответствовать логике проекта и данным.

Если по адресу, который должен быть виртуальным, случайно появился реальный каталог, условие !-d меняет маршрут обработки. При диагностике полезно проверить файловую систему: конфликт физического каталога с виртуальным разделом встречается после неаккуратного переноса и распаковки архивов.

В проектах с дополнительным роутингом, собственным API или изменённой точкой входа схема может отличаться. Не подменяйте проектную конфигурацию классическим примером только потому, что сайт построен на Битрикс.

Правильные 404 в Битрикс

Недостаточно указать ErrorDocument 404 /404.php и нарисовать красивую страницу «Не найдено». Необходимо, чтобы несуществующий товар, раздел и произвольный URL действительно возвращали HTTP 404, а не 200 с сообщением об ошибке.

В зависимости от компонента и реализации используются его настройки установки статуса, показа страницы 404 и выбора файла ошибки. Например, в ряде стандартных компонентов встречаются параметры SET_STATUS_404, SHOW_404 и FILE_404. Проверяйте параметры именно установленного компонента: нельзя переносить названия опций на все компоненты без исключений.

Для собственной PHP-логики статус задают до отправки заголовков, через подходящий API проекта или, в простом случае, http_response_code(404). Ошибки должны корректно обрабатываться и при включённом кеше. Проверьте не только HTML, но и заголовки настоящим GET-запросом.

Редиректы в Битрикс: порядок решает

Пользовательские внешние перенаправления обычно ставят до общего правила отправки запросов в /bitrix/urlrewrite.php. Иначе первоначальный адрес уже может быть переписан и нужное правило не сработает ожидаемым образом.

RewriteEngine On

# Во время проверки временный редирект.
RewriteRule ^old-catalog/item-a/?$ https://example.com/catalog/item-a/ [R=302,L]

# Ниже — штатная маршрутизация проекта, без удаления её условий.
Apache

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

HTTPS, Nginx и BitrixVM/BitrixEnv

В распространённой схеме Nginx принимает внешние подключения, обслуживает статику и передаёт PHP-запросы Apache. Конкретный состав зависит от окружения: встречаются и другие варианты, включая Nginx с PHP-FPM без Apache.

Если TLS завершается на Nginx, внутренний запрос к Apache может идти по HTTP. Проверка только %{HTTPS} !=on в .htaccess способна создать бесконечный редирект: снаружи HTTPS уже есть, а backend всё ещё видит незашифрованное соединение.

Лучшее место канонического перенаправления в такой архитектуре — внешний сервер или согласованная конфигурация виртуального хоста. Заголовки о протоколе и адресе клиента можно считать достоверными только после настройки доверенных прокси. Доверять любому присланному клиентом X-Forwarded-Proto нельзя.

Для BitrixVM/BitrixEnv учитывайте механизмы управления конфигурацией окружения. Правка автоматически генерируемого файла может исчезнуть после обновления или изменения настроек. Используйте предусмотренные точки расширения, храните изменения отдельно и проверяйте весь путь запроса.

Композитный сайт: почему .htaccess не управляет всем кешированием

Композитный режим сочетает подготовленный HTML и динамические области. В некоторых конфигурациях готовую страницу отдаёт Nginx, не запуская Apache и PHP. В этом случае rewrite-правила и заголовки из .htaccess не участвуют в таком ответе.

Если вы добавили запрет, редирект или заголовок, а посетители продолжают получать прежнюю страницу, проверьте композитный кеш, Nginx, CDN и браузер. Изменение правил безопасности должно закрывать путь к ресурсу на том уровне, который действительно его отдаёт.

Нельзя превращать весь HTML Битрикс в публичный длительный кеш одной строкой Cache-Control. Страницы с корзиной, ценами для разных групп, личными данными и авторизованными сессиями требуют учёта персонализации. Ошибка здесь опаснее медленной загрузки: она может раскрыть чужие данные.

Обмен с 1С и HTTP-авторизация

При обмене с учётной системой проблемы часто проявляются как 401, HTML вместо ожидаемого протокольного ответа или повторные запросы авторизации. Возможные причины — потеря Authorization между прокси и PHP, неверная схема HTTPS, дополнительный пароль на каталог, блокировка WAF, ограничения методов, размеры запросов и тайм-ауты.

В официальном уроке приведён исторический обход для CGI с REMOTE_USER и ручным разбором Basic Authorization. Его нельзя без анализа переносить в современную установку: обработчик PHP, цепочка прокси и способы передачи авторизации могли измениться. В частности, доступность переменных REMOTE_USER, REDIRECT_REMOTE_USER, HTTP_AUTHORIZATION, PHP_AUTH_USER и PHP_AUTH_PW зависит от конфигурации.

Диагностировать нужно конкретную точку обмена, например используемый вашим проектом обработчик в /bitrix/admin/, и реальный способ подключения 1С. Сначала проверяют доставку заголовка по цепочке серверов, затем реакцию приложения. Секреты и полный заголовок Authorization нельзя записывать в общедоступные журналы или публиковать в диагностических скриптах.

Не ставьте безусловный RewriteRule .* - [E=REMOTE_USER:...,L] над остальной маршрутизацией: [L] остановит текущий набор правил и может сломать ЧПУ. Не отключайте защиту всей административной директории ради одного обработчика — настройте минимально необходимые разрешения и проверку учётных данных.

.access.php — не .htaccess

.access.php используется механизмами разграничения прав Битрикс. Apache не интерпретирует этот файл как свою конфигурацию. Если приватный PDF лежит в публичном каталоге и веб-сервер отдаёт его напрямую, права CMS не обязательно участвуют в запросе.

Для действительно закрытых файлов используют непубличное хранилище и выдачу через приложение после проверки доступа либо специальный механизм защищённой передачи файла. При Nginx это может включать внутренние location и X-Accel-Redirect, при других схемах — иные серверные решения. Одной записи в .access.php для защиты любого статического URL недостаточно.

Каталог upload, резервные копии и служебные файлы

В пользовательских загрузках обычно не должно быть возможности исполнять PHP. Однако правило должно учитывать реальный PHP-handler и веб-сервер. Если запросы к .php напрямую обрабатывает Nginx с PHP-FPM, вложенный .htaccess не поможет.

Не закрывайте целиком /bitrix/ или /local/: внутри могут находиться необходимые публичные скрипты, стили, изображения, API и точки интеграции. Защищайте конкретные непубличные объекты, а не узнаваемое название каталога.

Особого внимания требуют конфигурационные файлы, дампы базы, архивы, журналы и резервные копии. То, что PHP-файл обычно исполняется без вывода исходного кода, не делает безопасной его копию с расширением .bak. Главная мера — не хранить секреты и резервные копии в доступном из интернета месте.

План диагностики проблем Битрикс после переноса

  1. Сверьте DocumentRoot, домены, сертификат и реальную архитектуру Nginx/Apache/PHP.
  2. Убедитесь, что перенесены корневой и вложенные .htaccess, а Apache разрешает нужные директивы.
  3. Проверьте доступность реальных файлов и каталогов, затем виртуальных адресов ЧПУ.
  4. Сравните /urlrewrite.php, настройки компонентов и каталог ЧПУ с прежним окружением.
  5. Проверьте 404, административную часть, загрузку файлов, REST/API и обмен с 1С.
  6. Проверьте HTTP-авторизацию без раскрытия секретов, а также ограничения на размер и время запросов.
  7. Проверьте кеши компонентов, управляемый и композитный кеш, Nginx и CDN.
  8. Проверьте приватные ресурсы прямыми запросами, в том числе минуя привычную навигацию сайта.

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

.htaccess в других распространённых CMS и платформах

Здесь перечислены распространённые системы, а не рейтинг по доле рынка. Их конфигурации различаются между версиями, редакциями и дистрибутивами. Общее правило: брать исходный файл из установленной версии продукта, а не из случайного универсального шаблона. CMS может использовать .htaccess одновременно для маршрутизации и защиты служебных файлов; восстановить только правила ЧПУ иногда недостаточно.

Joomla

В типичной поставке Joomla есть файл htaccess.txt, который служит основой для .htaccess на Apache. Перед переименованием нужно проверить, не существует ли уже рабочего .htaccess с настройками хостинга, HTTPS и безопасности. В таком случае файлы сравнивают и объединяют, а не перезаписывают вслепую.

В настройках Joomla различаются включение поисково-дружественных URL и использование переписывания URL. При работе через Apache последнее требует корректного mod_rewrite и серверных правил. Без переписывания в адресах может оставаться index.php; с правильно настроенным переписыванием запрос передаётся контроллеру без обязательного появления этого имени в публичном адресе.

В файле могут находиться не только правила маршрутизации, но и защитные проверки, обработка авторизации и специальные настройки. Параметр RewriteBase, если он требуется конкретной конфигурации, должен соответствовать базовому URL сайта, особенно при установке в подкаталог. Если Options +FollowSymLinks запрещён хостером, решение согласовывают с поддержкой, а не отключают все правила.

Характерная ситуация: главная страница открывается, а внутренние страницы возвращают 404 после включения переписывания. Проверяйте имя файла, область AllowOverride, наличие mod_rewrite, подкаталог установки и то, действительно ли запрос доходит до Apache. Штатный файл следует сохранять целиком и обновлять с учётом изменений продукта.

Drupal

В проектах Drupal с управлением зависимостями через Composer публичный корень нередко находится в каталоге web. В других структурах название или расположение может отличаться. DocumentRoot должен указывать именно на предусмотренный проектом публичный каталог. Направить его на весь репозиторий, а затем пытаться закрыть каждый секрет регулярными выражениями — слабая замена правильной архитектуре.

Поставляемый Drupal корневой .htaccess содержит больше, чем передачу запросов в index.php. В нём могут быть запреты доступа к конфигурации и служебным файлам, правила для скрытых путей, параметры обработчиков, сжатия и кеширования. В каталогах файлов также могут использоваться защитные .htaccess.

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

Открытые пользовательские файлы и приватное файловое хранилище имеют разные модели доступа. Приватные материалы желательно хранить вне публичного корня и выдавать через Drupal после проверки прав. На Nginx защитные правила .htaccess не действуют: необходимые запреты переносят в конфигурацию Nginx. Это особенно важно для загрузок и конфигурационных файлов.

OpenCart

Во многих дистрибутивах OpenCart пример Apache-конфигурации поставляется как .htaccess.txt. Его переименовывают в .htaccess после резервного копирования существующего файла. Для SEO URL обычно требуется также включить соответствующую возможность в настройках магазина и заполнить SEO-адреса сущностей.

Серверное правило передаёт путь приложению; затем OpenCart сопоставляет его товару, категории или другому маршруту. В ряде версий используется параметр _route_, но переносить такое правило между версиями и модификациями без проверки нельзя. Конфигурации OpenCart, ocStore и сборок с расширениями могут различаться.

Если ЧПУ работают только для части страниц, причина может быть в SEO-ключах, локализации, данных магазина или расширении маршрутизации, а не в Apache. Если не работает ни один красивый адрес, сначала проверяют серверный уровень.

После изменений тестируют не только карточки товаров, но и фильтры, поиск, пагинацию, сравнение, оформление заказа и уведомления платёжных систем. Нельзя удалять все параметры запроса ради «чистых URL»: в интернет-магазине они часто имеют функциональное назначение.

PrestaShop

PrestaShop может генерировать .htaccess на основании параметров магазина и настроек дружественных URL. Поэтому ручные изменения необходимо согласовывать с механизмом генерации: при сохранении настроек часть файла может обновиться.

Конфигурация зависит от базового URI, доменов, мультимагазинности, правил изображений и установленных модулей. У изображений могут быть специальные шаблоны адресов; заменить весь файл одним перенаправлением в index.php — значит рисковать не только страницами, но и медиакаталогом.

Пользовательские правила размещают вне перегенерируемых областей, если такая структура поддерживается конкретной версией, либо выносят в управляемую конфигурацию сервера. После регенерации делают сравнение файла с предыдущей версией. Отдельно проверяют несколько магазинов, языковые префиксы, картинки и платёжные callbacks.

Magento Open Source и Adobe Commerce

В проектах Magento 2 публичным корнем рекомендуется делать предусмотренный платформой каталог pub, а не корень всего проекта. Это уменьшает доступную по HTTP поверхность: исходный код, зависимости и конфигурация не должны становиться публичными только потому, что сервер смотрит слишком высоко в дереве каталогов.

В Apache-конфигурации Magento используются правила для входной точки приложения, статических ресурсов и медиа. В частности, URL статических файлов может содержать версию, которую сервер обрабатывает по специальным правилам. Вложенные .htaccess в соответствующих каталогах имеют значение; сохранять только корневой файл недостаточно.

Сбой картинок и стилей после развёртывания не всегда связан с .htaccess: проверяют режим приложения, публикацию статического содержимого, права, базовые URL, CDN и кеши. Проблема маршрутизации и отсутствие реально собранного ресурса — разные неисправности.

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

MODX Revolution

В типичных установках MODX исходный шаблон называется ht.access; для Apache его используют как основу файла .htaccess. Работа дружественных URL зависит одновременно от серверного переписывания и параметров MODX: псевдонимов, суффиксов, контейнеров, базового пути и контекстов.

Если страница открывается по системному адресу, но не по псевдониму, проверьте всю цепочку: файл Apache, настройки friendly URLs, уникальность псевдонима и актуальность кеша MODX. При многодоменной или многоконтекстной установке один глобальный редирект на фиксированный домен может разрушить выбор контекста.

Не переносите без анализа правила другого сайта: у него могут быть иная структура каталогов, скрытые служебные URL и другая схема формирования ссылок.

TYPO3

В Composer-проектах TYPO3 веб-корень обычно отделён от остального проекта; часто это public. Поставляемая серверная конфигурация учитывает маршрутизацию, доступ к файлам и другие требования платформы. Реальный URL страницы определяется не одним Apache: участвуют настройки сайта и маршрутизаторы TYPO3.

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

DLE и другие PHP-CMS

Для DataLife Engine и других PHP-систем принцип тот же: брать .htaccess из дистрибутива именно используемой версии. В таких CMS могут быть явные правила для отдельных типов страниц, а не один общий контроллер. Обновление структуры ЧПУ требует согласованного обновления серверных правил.

Если разработчик CMS предоставляет разные конфигурации для Apache и Nginx, это не взаимозаменяемые файлы. Используйте вариант для реальной схемы обслуживания сайта, включая reverse proxy и CDN.

Laravel и Symfony: не CMS, но важный смежный случай

Laravel и Symfony — фреймворки, на которых могут быть построены CMS и самостоятельные приложения. Для них принципиально правильное значение DocumentRoot: публичной должна быть предусмотренная проектом папка public, а не весь репозиторий.

У Laravel в публичном каталоге обычно есть Apache-правила, передающие запросы в index.php. У Symfony соответствующая конфигурация может устанавливаться отдельно, например через пакет поддержки Apache. Наличие и содержимое файла проверяют в конкретном проекте.

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

Облачные CMS и конструкторы

В управляемых сервисах наподобие Shopify, Wix, Tilda и в отдельных тарифах хостинговых платформ доступа к серверному .htaccess может не быть. Возможности зависят от продукта и режима размещения, а не только от названия CMS.

Редиректы, домены и заголовки там настраиваются средствами платформы, через разрешённые приложения или инфраструктуру перед ней. Загрузка файла с именем .htaccess в медиатеку ничего не настроит: файл должен находиться в подходящем каталоге Apache, а сам сервер — разрешать его обработку.

Диагностика: что делать, если .htaccess не работает

Сначала определите слой, на котором возникла ошибка

Один запрос может пройти CDN, балансировщик, Nginx, Apache, PHP-FPM, CMS и кеш приложения. Если CDN вернул сохранённый ответ, Apache вообще не участвовал в обработке. Если Nginx запретил путь, изменение Apache не отменит запрет. Если PHP вернул 404 из-за отсутствия записи, исправление RewriteRule не создаст эту запись.

В диагностике двигайтесь от наблюдаемого HTTP-ответа к конкретному слою. Зафиксируйте адрес, метод, время запроса, код, Location, заголовки кеша и соответствующие записи журналов. Не меняйте одновременно редиректы, настройки PHP и постоянные ссылки: после такого трудно установить причину.

Типичные симптомы

СимптомВозможная причинаС чего начать
Изменения совершенно не влияютNginx без Apache, другой DocumentRoot, запрет overrides, CDNПроверить архитектуру и нужный виртуальный хост
После добавления строки возникла 500Неподдерживаемая директива, запрещённый контекст, синтаксисОткатить изменение, открыть error log
Главная работает, внутренние страницы — 404Нет маршрутизации, неправильный базовый путь, правила CMSПроверить доставку запроса в front controller
ERR_TOO_MANY_REDIRECTSКонфликт HTTPS, домена или слешаПосмотреть всю цепочку Location
403 вместо страницыRequire, права файлов, запрет индекса, symlinkПроверить error log и доступ к конкретному файлу
Пропали CSS и изображенияОшибочные редиректы, rewrite статики, MIMEПроверить URL ресурсов отдельно
Не работает обмен с 1С или APIПотеря Authorization, Basic Auth поверх API, редирект POSTПроверить метод, заголовки и журналы интеграции
Изменения видны не всемCDN, кеш браузера, разные backend-узлыСравнить ответы и конфигурации всех узлов
502 или 504Недоступен либо медленно отвечает backendПроверить прокси и PHP-FPM, не только .htaccess

Безопасная проверка обработки файла

На тестовом окружении можно временно добавить перед маршрутизатором CMS правило для уникального пути:

RewriteEngine On
RewriteRule ^__htaccess_probe_a71c$ - [R=403,L]
Apache

Затем запросить именно этот путь и сравнить результат с контрольным запросом. Для кодов вне диапазона 3xx флаг R возвращает указанный статус без перенаправления; здесь ожидается 403. Сам по себе 403 ещё не доказывает работу правила, если такой же ответ уже давал WAF. Важна управляемая разница до и после изменения и соответствие журналов.

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

Команды curl

Получить заголовки обычного GET без вывода тела:

curl -sS -D - -o /dev/null https://example.com/catalog/
Bash

Посмотреть последовательность ответов при переходах:

curl -sS -L --max-redirs 10 -D - -o /dev/null http://example.com/catalog/
Bash

Вывести итоговый адрес и число переходов:

curl -sS -L -o /dev/null \
  -w 'status=%{http_code} redirects=%{num_redirects} final=%{url_effective}\n' \
  http://example.com/catalog/
Bash

curl -I отправляет HEAD, а приложение может обрабатывать HEAD иначе, чем GET. Для проверки пользовательской страницы надёжнее дополнительно выполнить обычный GET. Для API нужно тестировать реальные методы и тело на безопасных тестовых данных, а не делать вывод по главной странице.

Чтобы проверить конкретный сервер, сохранив домен и TLS SNI, администратор может использовать:

curl --resolve example.com:443:192.0.2.10 \
  -sS -D - -o /dev/null https://example.com/catalog/
Bash

Здесь IP демонстрационный. Такая проверка имеет смысл, если прямой доступ к серверу предусмотрен архитектурой и разрешён. Она не воспроизводит все преобразования CDN и не должна становиться поводом открыть origin всему интернету. Не используйте -k как обычное решение проблем сертификатов.

Журналы Apache и трассировка rewrite

Конкретные пути access log и error log зависят от системы и виртуального хоста. В панели хостинга обычно есть отдельный просмотр журналов. Ищите запись на момент ошибки, а не произвольную старую строку.

Характерные сообщения Invalid command, not allowed here, Permission denied и превышение числа внутренних перенаправлений указывают на разные классы проблем. По одному коду 500 различить их нельзя.

В основной конфигурации Apache администратор может временно включить:

LogLevel warn rewrite:trace3
Apache

Это не универсальная инструкция для вставки в .htaccess: настройка применяется на серверном уровне или в виртуальном хосте. Трассировка показывает проходы rewrite, но увеличивает нагрузку и объём журналов. В журнал могут попасть параметры запросов; защищайте его и отключайте подробную трассировку после диагностики. Старые инструкции с RewriteLog и RewriteLogLevel не подходят для Apache 2.4.

Почему apachectl -t недостаточно

apachectl -t<br>apachectl -M
Bash

Первая команда проверяет основную конфигурацию, вторая показывает загруженные модули. В зависимости от дистрибутива вместо apachectl используют apache2ctl или другой путь к исполняемому файлу.

Успешный configtest не гарантирует корректность всех .htaccess. Эти файлы обрабатываются при запросах к соответствующим каталогам и не обязательно прочитываются тестом основной конфигурации. Поэтому после проверки конфигурации необходимы HTTP-тесты нужных маршрутов, включая вложенные каталоги.

Минимальный набор проверок после изменения

  1. Главная страница и несколько внутренних страниц возвращают ожидаемые 200.
  2. Существующий файл открывается напрямую, а отсутствующий получает корректный 404.
  3. HTTP и альтернативный домен переходят на выбранную каноническую версию без циклов.
  4. Вход, выход, восстановление пароля и административная часть работают.
  5. Формы, поиск, REST API и AJAX проходят штатно.
  6. Для магазина проверены корзина, оформление, уведомления оплаты и обмен с учётной системой.
  7. Служебные файлы и закрытые каталоги не стали доступны.
  8. Сжатие и кеширование соответствуют типу содержимого; личные данные не попадают в публичный кеш.
  9. Проверены sitemap, robots.txt, ACME challenge при его использовании и задачи внешнего мониторинга.
  10. Для многосайтовости проверен каждый домен, а не только основной сайт.

Как организовать правила и внедрять изменения

Не существует одного идеального .htaccess для всех сайтов

Конфигурация зависит от DocumentRoot, сервера перед Apache, версии CMS, обработчика PHP, модулей, интеграций, схемы кеширования и прав хостинга. Большой файл из десятков «улучшений» обычно менее надёжен, чем небольшая конфигурация с понятными обязанностями.

Вместо универсального файла используйте архитектуру правил:

  1. Комментарий о проекте и владельце конфигурации
  2. Базовые настройки каталога и ограничения доступа
  3. Проверенные правила внешних перенаправлений
  4. Специальные маршруты и необходимые исключения
  5. Уравляемые блоки кеша и других расширений в нужном им месте
  6. Штатный маршрутизатор CMS
  7. Независимые настройки заголовков, MIME и ошибок

Это логическая схема, а не порядок выполнения всех модулей Apache. Header, авторизация, mod_alias и mod_rewrite работают на разных стадиях обработки. Внутри mod_rewrite порядок строк особенно важен; для других директив нужно учитывать их контекст и правила объединения. Плагин кеширования может требовать конкретное расположение блока — соблюдайте документацию именно этого плагина.

Изменения небольшими шагами

Сначала сохраните исходный файл вне публичного дерева и убедитесь, что сможете восстановить его независимо от CMS. Внесите одно логическое изменение. Проверьте синтаксис основной конфигурации, если меняли её, и выполните HTTP-тесты. Затем проверьте журналы, только после этого переходите к следующей задаче.

Для редиректов начинайте с временного статуса, когда это допустимо. После подтверждения поведения заменяйте его на постоянный. Браузеры и промежуточные кеши могут надолго запомнить ошибочный 301; восстановление файла не обязательно немедленно исправит поведение у всех посетителей.

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

Разделяйте автоматические и ручные блоки

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

Если файл хранится в Git, исключите секреты и различайте настройки окружений. Абсолютные пути к файлам паролей, реальные адреса служебных сетей и домены тестового стенда не следует бездумно переносить на production. Резервные копии конфигурации не должны раздаваться веб-сервером.

Когда лучше отказаться от .htaccess

При полном административном доступе правила обычно удобнее и эффективнее хранить в конфигурации виртуального хоста или подходящем <Directory>. Это устраняет необходимость искать рапределённые файлы и централизует контроль изменений.

Но перенос не всегда означает простое копирование строк: RewriteRule в контексте виртуального хоста и в контексте каталога сопоставляет пути по-разному. Переход с Apache на Nginx также требует перевода логики, а не переименования файла.

Перед отключением overrides проверьте все вложенные .htaccess, в том числе созданные CMS для безопасности загрузок и закрытых данных. Перенесите не только красивые URL, но и запреты исполнения, ограничения доступа и служебные настройки. После миграции обязательно проверьте, что ранее закрытые файлы по-прежнему закрыты.

Частые вопросы и распространённые мифы

Обязателен ли .htaccess для каждого сайта?

Нет. Он нужен, когда Apache или совместимый сервер использует распределённую конфигурацию. Такой же результат можно получить в основной конфигурации сервера. На Nginx этот файл не действует.

Это файл WordPress или Apache?

Это механизм веб-сервера. WordPress, Битрикс и другие CMS могут поставлять его или изменять отдельные блоки, но читается он не как PHP-код CMS, а как конфигурация Apache.

Можно ли просто скачать чужой файл?

Использовать его как материал для изучения — да. Устанавливать целиком без проверки окружения — нет. Даже два сайта на одной CMS могут иметь разные каталоги, сеть сайтов, маршруты, плагины и способы обработки PHP.

Нужно ли перезапускать Apache?

После изменения самого .htaccess обычно нет: правила применяются к последующим запросам. Для изменения конфигурации виртуального хоста, модулей или AllowOverride требуется процедура применения серверной конфигурации. Совместимые серверы могут иметь собственные особенности перечитывания.

Поможет ли chmod 777?

Это не исправление правил и не способ включить mod_rewrite. Избыточные права увеличивают риск изменения конфигурации посторонним процессом. Нужны правильный владелец, доступ по всей цепочке каталогов и минимальные необходимые разрешения.

Можно ли удалить .htaccess, если сайт работает?

Не следует делать это без аудита. Главная страница может продолжить работать, а внутренние адреса, авторизация API или защита резервных копий — перестать. Работоспособность нескольких страниц не доказывает ненужность файла.

Защищает ли Options -Indexes от скачивания файлов?

Нет. Директива запрещает автоматически показывать список содержимого каталога. Зная прямой URL файла, посетитель всё ещё может получить его, если нет отдельного запрета.

Запрет в robots.txt делает файл закрытым?

Нет. robots.txt — рекомендации роботам, а не контроль доступа. Конфиденциальные данные защищают правами, авторизацией, конфигурацией сервера и размещением вне публичного каталога.

Можно ли скрыть технологию сайта с помощью .htaccess?

Часть информационных заголовков и подписей убрать можно, но это не устраняет уязвимости. CMS часто определяется по путям ресурсов и содержимому страниц. Обновления, ограничения прав и защита данных важнее маскировки.

Улучшит ли .htaccess SEO сам по себе?

Нет. Он помогает реализовать технические условия: корректные перенаправления, единый адрес страницы, реальные 404 и 410, доступность ресурсов. Качество контента и корректность бизнес-логики он не заменяет. rel="canonical", внутренние ссылки и sitemap также должны согласовываться с выбранной адресацией.

Нужно ли запрещать всем поисковым роботам параметры URL?

Нет. Параметры могут управлять фильтрами, языком, пагинацией и полезными страницами. Массовое удаление query string способно сломать сайт. Решения принимают по назначению конкретных параметров и согласуют с CMS.

Можно ли заменить WAF набором RewriteCond?

Нет. Простые правила полезны для точных известных случаев, но поиск «опасных слов» в запросах даёт ложные срабатывания и легко обходится кодированием. Нужны обновления, безопасный код, ограничения ресурсов и специализированные средства защиты.

Почему на локальном сервере работает, а на хостинге нет?

Могут различаться версия Apache, набор модулей, AllowOverride, контекст правил, регистр файлов, права, наличие proxy, обработчик PHP и версия CMS. Сравнивать нужно окружения, а не только содержимое .htaccess.

Можно ли настроить PHP CLI или cron через .htaccess?

Нет. CLI не выполняет HTTP-запрос через Apache и не читает этот файл. Для CLI и задач cron нужны их собственные настройки PHP и окружения. Настройки PHP-FPM тоже не становятся автоматически настройками CLI.

Что важнее: .htaccess или настройки CMS?

Они решают разные задачи. Сервер должен корректно доставить запрос и применить свои ограничения, а CMS — распознать маршрут, проверить права и сформировать ответ. Если CMS решила перенаправить адрес после запуска PHP, отсутствие аналогичного правила в .htaccess не отменит этот редирект.

Краткий словарь

DocumentRoot — каталог файловой системы, из которого виртуальный хост обычно обслуживает сайт. Он не обязательно совпадает с корнем репозитория.

Виртуальный хост — набор серверных настроек для определённого сайта или группы адресов.

Директива — инструкция конфигурации, например DirectoryIndex или RewriteRule.

Модуль Apache — компонент, реализующий определённую функциональность. Например, mod_rewrite занимается преобразованием адресов.

ЧПУ — человекопонятный URL: адрес вроде /catalog/notebooks/ вместо технического URL с идентификаторами. Внутри приложение всё равно может работать с числовыми ID.

Front controller — входной скрипт, который принимает множество маршрутов и передаёт запрос нужной части приложения.

Rewrite — внутреннее изменение обработки запроса без обязательного изменения адреса в браузере.

Redirect — ответ, предлагающий клиенту выполнить новый запрос по другому адресу.

Origin — в контексте CDN исходный сервер сайта; в контексте браузерной безопасности комбинация схемы, имени хоста и порта. Значение зависит от обсуждаемой задачи.

Reverse proxy — сервер перед приложением, принимающий клиентские запросы и передающий их внутренним серверам.

Query string — часть URL после ?, содержащая параметры запроса.

SAPI — интерфейс запуска PHP: например, модуль Apache, CGI/FastCGI или CLI.

Итоги

.htaccess — не магический файл ускорения и не набор обязательных SEO-команд. Это инструмент распределённой настройки Apache, который позволяет менять обработку запросов, не редактируя основную конфигурацию сервера.

Для новичка главное — понять разницу между перенаправлением и внутренней маршрутизацией, сохранять резервную копию и не копировать чужие правила целиком. Для разработчика — учитывать контекст, повторные проходы rewrite, наследование, границы доверия proxy и взаимодействие нескольких уровней кеша.

В WordPress особое внимание нужно уделить управляемому блоку постоянных ссылок, Multisite, подкаталогам и расширениям, которые переписывают конфигурацию. В 1С-Битрикс — связке серверного rewrite с /bitrix/urlrewrite.php и /urlrewrite.php, вложенным файлам, ЧПУ компонентов, обмену с 1С и композитному кешу.

Хорошая конфигурация не обязательно длинная. Она понятна, соответствует реальному окружению, не конфликтует с CMS и проверена на тех запросах, от которых зависит работа сайта.

Поделиться:
Николай Тютин

Администратор и автор блога

Оцените автора
( Пока оценок нет )
NICK AIR – Блог Николая Тютина
Добавить комментарий