Файл .htaccess позволяет настраивать Apache прямо в папке сайта без доступа к конфигурации сервера. Он находится в public_html/.
301 редиректы
RewriteEngine On
# Со старой страницы на новую
Redirect 301 /old-page.html /new-page
# Редирект всей папки
RedirectMatch 301 ^/old-section/(.*)$ /new-section/$1
www ↔ без www
RewriteEngine On
# Перенаправить ВСЕ запросы на www
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
# Или наоборот — убрать www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
HTTP → HTTPS редирект
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Защита папки паролем
# Создайте файл .htpasswd:
# htpasswd -c /home/user/.htpasswd adminuser
# В .htaccess папки:
AuthType Basic
AuthName "Protected Area"
AuthUserFile /home/user/.htpasswd
Require valid-user
Блокировка IP-адресов
# Заблокировать конкретный IP
Deny from 203.0.113.42
# Разрешить только свой IP
Order deny,allow
Deny from all
Allow from 203.0.113.10
Кэширование статических файлов
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
Порядок правил имеет значение
Если объединить редирект на HTTPS и добавление www в одном файле бездумно, легко получить двойной редирект или зацикливание — Apache применяет правила по порядку сверху вниз и останавливается только на первом сработавшем флаге L.
# Правильный порядок: сначала HTTPS, затем www,
# чтобы браузер не делал два отдельных редиректа подряд
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
Оба условия ведут на один и тот же итоговый адрес с www и HTTPS одновременно — так браузер получает один редирект вместо двух последовательных.
Безопасное тестирование правил
Каждое серьёзное изменение проверяйте с сохранённой резервной копией рядом — правило можно откатить мгновенно, не дожидаясь восстановления из панели хостинга.
# Перед правкой сохранить рабочую копию
cp .htaccess .htaccess.bak
# Если сайт упал с 500 после правки — вернуть прежнюю версию одной командой
cp .htaccess.bak .htaccess
Типичные ошибки в .htaccess
| Симптом | Причина |
|---|---|
| 500 Internal Server Error сразу после сохранения | Синтаксическая ошибка в директиве: пропущен пробел между RewriteCond и шаблоном, лишняя кавычка или неверный флаг вроде [R=301,L,X] |
| RewriteRule: bad flag delimiters | Флаги в квадратных скобках записаны без запятой между ними или с лишним пробелом внутри скобок |
| ERR_TOO_MANY_REDIRECTS в браузере | Правило www ↔ без www и HTTP → HTTPS конфликтуют по порядку, особенно если на Cloudflare уже включён Flexible SSL и повторное правило перенаправляет туда-обратно |
| Invalid command 'ExpiresActive' | Директива используется без обёртки <IfModule mod_expires.c>, а модуль на аккаунте отключён — Apache не понимает команду и падает с 500 |
| Basic Auth не спрашивает пароль | Файл .htpasswd указан неверным абсолютным путём или у него нет прав на чтение процессом Apache |
Когда .htaccess не подходит
- Сайт работает на Nginx — .htaccess читает только Apache, для Nginx правила переписываются в конфиг виртуального хоста на стороне провайдера
- Правил становится много и они лежат в подпапках — при AllowOverride All Apache сканирует дерево директорий на каждый запрос, что заметно замедляет ответ
- Нужно менять настройки, не разрешённые в AllowOverride (лимиты процесса, модули ядра) — .htaccess переопределяет только то, что явно открыто хостингом
- Изменения нужно применить сразу к сотням доменов — держать идентичный файл в каждой папке неудобно, синхронизация легко расходится
Проверка результата
После правки всегда проверяйте реальный HTTP-ответ, а не только внешний вид страницы в браузере — код ответа виден не всегда, особенно если сработал кэш. Если правила редиректа связаны с миграцией на HTTPS, см. также статью про настройку HTTPS-редиректа; при ошибке 500 разбор причин — в статье про диагностику error_log.
# Проверить код ответа и адрес назначения редиректа
curl -I http://example.com/old-page.html
# Убедиться, что заголовки кэширования применились к статике
curl -I https://example.com/style.css | grep -i cache-control