Рецепты .htaccess
Готовые блоки .htaccess под типовые задачи: вставляйте в файл .htaccess в корне сайта (или в нужном каталоге), перед каждым блоком указано, что он делает. При сомнениях прогоните файл через линтер /check/, а правила mod_rewrite — через тестер /rewrite/; собрать .htaccess из чекбоксов можно в генераторе. Плейсхолдеры (example.com, 203.0.113.x, пути-примеры) замените на свои. А как работает mod_rewrite — в туториале «Как работает mod_rewrite».
Если ищете именно про защиту сайта — отдельный гид «Безопасность сайта через .htaccess» собирает все «защитные» рецепты вместе с разбором: заголовки безопасности, закрытие файлов, доступ по IP, пароль, запрет PHP в загрузках, анти-бот.
А про скорость — гид «Ускорение сайта через .htaccess»: кэш статики, gzip / Brotli, ETag, preload-подсказки.
Не уверены в регулярках внутри правил? — справочник «PCRE: регулярные выражения для mod_rewrite» (якоря, классы, кванторы, группы, экранирование).
Для WordPress — отдельный хаб: «.htaccess для WordPress» (стандартный файл, защита wp-config/wp-login/xmlrpc, кэш, частые проблемы); для других CMS/фреймворков (Laravel, Joomla, Drupal, Bitrix, Yii…) — хаб «.htaccess для CMS и фреймворков»; всё про SEO и редиректы (301 vs 302, переезд домена, цепочки) — хаб «SEO и редиректы через .htaccess»; краткая шпаргалка и готовые .htaccess под задачу.
1. Редирект с www на без www (и обратно)
Зачем: склейка зеркал, один канонический хост — лучше для SEO и куки.
RewriteEngine On # www.example.com -> example.com RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
RewriteEngine On # example.com -> www.example.com RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Как работает: RewriteCond ловит хост, начинающийся с www.; %1 — это всё после www. (захваченная группа условия); [R=301,L] — постоянный редирект, на нём обработка останавливается. Меняйте https на http, если у сайта нет TLS.
→ собрать в генераторе (блок «WWW») · → проверить на конкретном URL
2. Принудительный HTTPS
Зачем: весь трафик по защищённому соединению; нужен установленный сертификат.
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteEngine On RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Как работает: если соединение не по HTTPS — 301 на тот же URL по https://. Ставьте это правило раньше остальных rewrite-правил. За прокси/CDN %{HTTPS} может всегда быть off — тогда проверяйте заголовок %{HTTP:X-Forwarded-Proto} (второй вариант).
→ собрать в генераторе (блок «Редирект на HTTPS») · → проверить на конкретном URL
3. 301-редирект старой страницы на новую (и массовый список)
Зачем: перенос/переименование страниц без потери позиций и ссылок.
Redirect 301 /old-page.html /new-page.htmlRewriteEngine On RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
Как работает: Redirect 301 <старый-путь> <новый-путь-или-URL> — точное совпадение пути. Для целого раздела используйте RedirectMatch 301 ^/old-section/(.*)$ /new-section/$1. Десятки/сотни редиректов удобнее сгенерировать пакетно.
→ пакетный генератор 301-редиректов из списка «старый URL → новый URL» · → проверить на конкретном URL
4. Убрать .php (или .html) из URL
Зачем: красивые URL вида /about вместо /about.php.
RewriteEngine On # если запрошен не существующий файл/каталог, но есть <имя>.php — отдать его RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule ^([^.]+)$ $1.php [L]
RewriteCond %{THE_REQUEST} \s/+([^.\s]+)\.php[\s?] [NC] RewriteRule ^ /%1 [R=301,L]
Как работает: первый блок внутренне подставляет .php к запросу без расширения, если такой файл существует; второй (опционально) убирает .php из адресной строки 301-редиректом. [L] — стоп.
→ пошагово проверить · → проверить синтаксис
5. Своя страница ошибки 404 / 403 / 500
Зачем: вместо стандартной серверной заглушки — ваша страница с навигацией.
ErrorDocument 404 /404.html ErrorDocument 403 /403.html ErrorDocument 500 /500.html
Как работает: при ошибке с указанным кодом Apache внутренне отдаёт ваш файл (статус остаётся 404/403/500). Убедитесь, что сама страница ошибки доступна и не вызывает ту же ошибку.
→ собрать в генераторе (блок «Страницы ошибок») · → проверить синтаксис
6. Защита папки паролем (Basic Auth)
Зачем: закрыть админку/каталог простым логином-паролем.
AuthType Basic AuthName "Закрытая зона" AuthUserFile "/srv/site/.htpasswd" Require valid-user
Как работает: AuthUserFile — абсолютный путь к файлу .htpasswd (его лучше держать вне DocumentRoot); Require valid-user — пускать любого из этого файла (либо Require user alice bob — только указанных). Сам .htpasswd — это строки логин:хеш (рекомендуется bcrypt). Дополнительно закройте сам .htpasswd от веба правилом из рецепта 7.
→ генератор содержимого .htpasswd и этого блока · → подробная статья о парольной защите
7. Запрет доступа к файлам и каталогам
Зачем: спрятать .env, wp-config.php, дампы БД, .git/, служебные каталоги.
<FilesMatch "(^\.|\.env$|\.sql$|\.bak$|\.log$|composer\.(json|lock)$)"> Require all denied </FilesMatch>
Require all deniedКак работает: <FilesMatch> применяет правило к файлам, чьё имя матчит regex; Require all denied — 403 для всех. Каталог .git/ обычно закрывают отдельным правилом RedirectMatch 404 ^/\.git или блоком на <DirectoryMatch> (в .htaccess доступен RedirectMatch).
→ проверить синтаксис · → если у вас старый Order/Deny
8. Блокировка по IP-адресу
Зачем: отрезать конкретного посетителя/подсеть (спам, брутфорс).
<RequireAll> Require all granted Require not ip 203.0.113.10 Require not ip 203.0.113.0/24 </RequireAll>
Require ip 203.0.113.0/24 Require ip 198.51.100.7
Как работает: <RequireAll> требует выполнения всех вложенных условий: доступ разрешён всем (Require all granted), кроме перечисленных IP/подсетей (Require not ip …).
→ перевести старый Order/Allow/Deny в этот синтаксис · → подробная статья о фильтрации по IP
9. Блокировка ботов по User-Agent
Зачем: отсечь агрессивные SEO-сканеры/скраперы, экономия ресурсов.
RewriteEngine On RewriteCond %{HTTP_USER_AGENT} (AhrefsBot|SemrushBot|MJ12bot|DotBot|PetalBot|DataForSeoBot|BLEXBot) [NC] RewriteRule ^ - [F]
Как работает: если строка User-Agent содержит одно из имён (без учёта регистра) — [F] отдаёт 403, - означает «подстановки нет, только применить флаг».
→ собрать в генераторе (блок «Блокировка ботов» — там список можно собрать чекбоксами) · → проверить на конкретном URL
10. Защита картинок от хотлинка
Зачем: чужие сайты не должны показывать ваши картинки со своих страниц (воровство трафика).
RewriteEngine On RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^https?://([a-z0-9-]+\.)?example\.com [NC] RewriteRule \.(jpe?g|png|gif|webp|svg)$ - [F,NC]
Как работает: если у запроса картинки есть Referer (не пустой) и он не с вашего домена — 403. Пустой Referer (прямой заход, сохранение картинки) пропускаем. Замените example.com на свой домен; при необходимости вместо [F] можно отдавать «заглушку»: RewriteRule \.(jpe?g|png|gif)$ /hotlink.png [L,NC].
→ собрать в генераторе (блок «Защита от хотлинка») · → проверить на конкретном URL
11. Заголовки безопасности
Зачем: базовая защита от кликджекинга, MIME-sniffing, утечки реферера.
<IfModule mod_headers.c> Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()" # HSTS — включайте только когда уверены, что сайт навсегда на HTTPS: # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" </IfModule>
Как работает: Header always set добавляет заголовок к любому ответу (включая ошибки). X-Frame-Options: SAMEORIGIN запрещает встраивать сайт в <iframe> с других доменов; nosniff запрещает браузеру «угадывать» MIME-тип. HSTS оставлен закомментированным намеренно: с ним сайт нельзя будет открыть по http:// в течение max-age — включайте осознанно.
→ собрать в генераторе (блок «Security headers» — соберёт нужные заголовки чекбоксами) · → подробнее про каждый заголовок (CSP, HSTS, CORS, кэш) — справочник HTTP-заголовков
12. Кэширование статики в браузере
Зачем: повторные визиты загружаются быстрее, меньше запросов к серверу.
<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 image/svg+xml "access plus 1 year" ExpiresByType image/x-icon "access plus 1 year" ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" ExpiresByType application/font-woff2 "access plus 1 year" ExpiresByType text/html "access plus 0 seconds" </IfModule>
Как работает: ExpiresByType <mime> "access plus <срок>" ставит заголовки Expires и Cache-Control: max-age=…. HTML кэшировать надолго не стоит (0 seconds), иначе пользователи будут видеть старую версию. После выкладки новой версии файла меняйте его имя (style.v2.css) — иначе из кэша возьмётся старый.
→ собрать в генераторе (блок «Кэш статики»)
13. Сжатие GZIP
Зачем: текстовые ответы (HTML/CSS/JS) передаются в 3–5 раз меньше по объёму.
<IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css AddOutputFilterByType DEFLATE application/javascript application/json AddOutputFilterByType DEFLATE application/xml application/rss+xml AddOutputFilterByType DEFLATE image/svg+xml application/vnd.ms-fontobject font/ttf font/otf </IfModule>
Как работает: AddOutputFilterByType DEFLATE <mime…> включает gzip-сжатие для перечисленных типов. Уже сжатые форматы (JPEG, PNG, WEBP, ZIP, PDF) сжимать не нужно — выигрыша нет. Если на хостинге доступен Brotli, аналогично работает mod_brotli (AddOutputFilterByType BROTLI_COMPRESS …).
→ собрать в генераторе (блок «GZIP»)
14. Отключить листинг каталога
Зачем: чтобы посетитель не видел содержимое каталога без index.*-файла.
Options -IndexesКак работает: Options -Indexes убирает автогенерируемый список файлов; вместо него вернётся 403. Если хостинг запрещает менять Options через .htaccess, появится ошибка 500 — тогда уберите эту строку.
→ собрать в генераторе (блок «Options»)
15. Своя стартовая страница каталога
Зачем: указать, какой файл отдавать при заходе на / или /каталог/.
DirectoryIndex index.php index.html home.htmlКак работает: Apache берёт первый существующий файл из списка (слева направо). Полезно, если стартовый файл называется не index.html (например home.php) или нужно отдать предпочтение .php над .html.
16. Режим обслуживания (с белым списком по IP)
Зачем: на время работ показывать всем «сайт на обслуживании», но себя пускать.
RewriteEngine On RewriteCond %{REMOTE_ADDR} !^203\.0\.113\.10$ RewriteCond %{REQUEST_URI} !^/maintenance\.html$ [NC] RewriteCond %{REQUEST_URI} !\.(css|js|png|jpe?g|svg|ico|woff2?)$ [NC] RewriteRule ^ /maintenance.html [R=503,L] ErrorDocument 503 /maintenance.html <IfModule mod_headers.c> Header always set Retry-After "3600" </IfModule>
Как работает: всех, кроме вашего IP, перенаправляет на /maintenance.html с кодом 503 (а не 200 — это важно: 503 говорит поисковикам «временно, зайдите позже», статика при этом грузится — последнее RewriteCond исключает CSS/JS/картинки). Retry-After: 3600 — подсказка «вернитесь через час». Не забудьте убрать этот блок после работ.
→ собрать в генераторе (блок «Режим обслуживания») · → проверить на конкретном URL
Инструменты и статьи
Генератор .htaccess · Пакетный генератор 301-редиректов · Генератор .htpasswd · Конвертер Apache 2.2 → 2.4 · Проверка .htaccess (линтер) · Тестер RewriteRule
Статьи: Фильтрация по IP · Парольная защита · Блокировка по referer