# Настройка .htaccess для 1С-Битрикс: полное руководство

URL: https://dmeshcheryakov.ru/blog/bitrix-htaccess-config/
Раздел: 1С-Битрикс
Теги: 1С-Битрикс, .htaccess, Apache, SEO
Опубликовано: 2019-08-04
Обновлено: 2026-09-07
Автор: Дмитрий Мещеряков (https://dmeshcheryakov.ru)

> Оптимальная конфигурация .htaccess: редиректы, ЧПУ, сжатие, кэширование браузера. Готовые примеры для production.

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

Ниже — разбор того, что действительно нужно в `.htaccess` для Битрикса, что туда попадает по инерции, и три директивы, которые чаще всего и кладут сайт при переезде на новый сервер.

**Сначала проверьте, читается ли ваш `.htaccess` вообще.** На типовой конфигурации BitrixVM перед Apache стоит nginx, и статику — картинки, CSS, JS — он отдаёт сам, не доходя до Apache. Всё, что вы напишете в `.htaccess` про сжатие и заголовки кэширования для статических файлов, в этом случае просто не выполнится, а вы будете полдня выяснять, почему заголовки не меняются. Проверяется одной командой: `curl -I https://site.ru/bitrix/js/main/core/core.js` — по заголовку `Server` видно, кто ответил.

И второе: `.htaccess` читается Apache при **каждом** запросе, для каждой директории в пути. Если у вас есть доступ к конфигу виртуального хоста — правила там работают быстрее, а `AllowOverride None` убирает лишние обращения к диску.

## Где лежит .htaccess и как его править

Файл `.htaccess` находится в корне сайта. Редактируйте через SFTP/FTP (FileZilla, WinSCP), а не через админку Битрикса.

**Важно:** Перед изменением сделайте резервную копию файла. Ошибка в .htaccess может привести к 500 ошибке на всём сайте.

## Базовая конфигурация

```apache
# Кодировка по умолчанию
AddDefaultCharset utf-8

# Отключаем листинг директорий
Options -Indexes

# Отключаем обработку SSI
Options -IncludesNoExec

# Включаем символические ссылки
Options +FollowSymLinks

# Обработка PHP.
# ВНИМАНИЕ: директивы php_flag/php_value понимает только mod_php.
# На PHP-FPM (а это большинство современных серверов) они дают
# 500 Internal Server Error — см. предупреждение ниже
php_flag display_errors off
php_flag allow_url_fopen on

# Защита служебных файлов.
# Синтаксис Apache 2.4; для 2.2 использовался Order/Deny
<Files *.sql>
    Require all denied
</Files>

<FilesMatch "\.(log|bak|sql|sql\.gz|tar|zip)$">
    Require all denied
</FilesMatch>

# Включаем mod_rewrite
<IfModule mod_rewrite.c>
    RewriteEngine On
</IfModule>
```

**Три директивы, которые кладут сайт при переезде на новый сервер.** Все три дают одинаковый симптом — 500 на всём сайте и запись «Invalid command» в error.log Apache.

**`php_flag` и `php_value`.** Работают только с `mod_php`. На PHP-FPM Apache их не понимает. Настройки PHP в этом случае задаются в пуле FPM или через `.user.ini` в корне сайта.

**`Order`, `Deny from`, `Allow from`.** Это синтаксис Apache 2.2. В 2.4 он поддерживается только при подключённом `mod_access_compat`, которого в минимальных сборках нет. Современный эквивалент — `Require all denied` / `Require all granted`.

**`Options +FollowSymLinks`.** Если хостер запретил переопределять `Options` через `AllowOverride`, эта строка тоже даёт 500. При проблемах пробуйте `Options +SymLinksIfOwnerMatch`.

Отсюда практическое правило: после любой правки `.htaccess` первым делом смотрите не на сайт, а в `error.log` Apache — там будет точная строка и номер.

## Редиректы

### 1. С www на без www (или наоборот)

```apache
# С www на без www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# Или с без www на www
# RewriteCond %{HTTP_HOST} !^www\. [NC]
# RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]
```

### 2. С HTTP на HTTPS

```apache
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
```

### 3. Удаление index.php

```apache
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^(.*)index\.php$ /$1 [R=301,L]
```

### 4. Добавление слэша в конце URL

```apache
# Только для директорий, не для файлов
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]{1,5}$
RewriteRule ^(.*)$ $1/ [R=301,L]
```

### 5. Удаление дублирующихся слэшей

```apache
RewriteCond %{THE_REQUEST} //
RewriteRule ^.*$ /$0 [R=301,L]
```

**Проверяйте цепочки редиректов, а не отдельные правила.** Каждое из правил выше по отдельности корректно, но вместе они складываются: запрос на `http://www.site.ru/catalog/index.php` пройдёт через убирание `www`, переход на HTTPS, удаление `index.php` и добавление слэша — четыре последовательных 301. Для пользователя это лишние круги, для поисковика — размытие сигнала, а на длинной цепочке часть роботов просто перестаёт идти дальше.

Проверять нужно так: `curl -sIL http://www.site.ru/catalog/index.php | grep -E "^(HTTP|Location)"`. Идеал — один редирект на конечный адрес; порядок правил в файле для этого важнее их содержимого.

## ЧПУ для Битрикс

```apache
<IfModule mod_rewrite.c>
    RewriteEngine On
    
    # Базовая директория
    RewriteBase /
    
    # Если файл или директория существует — отдаём как есть
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    
    # Иначе передаём в Битрикс
    RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
</IfModule>
```

## Сжатие (mod_deflate)

```apache
<IfModule mod_deflate.c>
    # Сжимаем текстовые файлы
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE image/svg+xml
    
    # Исключаем браузеры с проблемами
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
</IfModule>
```

## Кэширование браузера

```apache
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    
    # HTML — без кэша
    ExpiresByType text/html "access plus 0 seconds"
    
    # Данные — без кэша
    ExpiresByType application/json "access plus 0 seconds"
    ExpiresByType application/xml "access plus 0 seconds"
    
    # RSS/Atom
    ExpiresByType application/rss+xml "access plus 1 hour"
    ExpiresByType application/atom+xml "access plus 1 hour"
    
    # Favicon
    ExpiresByType image/x-icon "access plus 1 week"
    ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
    
    # Медиа
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 month"
    ExpiresByType video/mp4 "access plus 1 year"
    ExpiresByType audio/mp3 "access plus 1 year"
    
    # Шрифты
    ExpiresByType font/woff "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
    ExpiresByType application/font-woff "access plus 1 year"
    ExpiresByType application/font-woff2 "access plus 1 year"
    
    # CSS и JS
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType text/javascript "access plus 1 year"
</IfModule>

# Cache-Control заголовки
<IfModule mod_headers.c>
    # Статика — долгий кэш
    <FilesMatch "\.(ico|jpg|jpeg|png|gif|webp|svg|woff|woff2|css|js)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
    
    # HTML — без кэша
    <FilesMatch "\.(html|htm|php)$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
    </FilesMatch>
</IfModule>
```

## Почему «защита» из регулярок в .htaccess вредна

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

```apache
# Блокировка сканеров уязвимостей
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule .* - [F,L]

# Защита от SQL-инъекций
RewriteCond %{QUERY_STRING} union.*select.*\( [NC,OR]
RewriteCond %{QUERY_STRING} concat.*\( [NC]
RewriteRule .* - [F,L]

# Блокировка подозрительных User-Agent
<IfModule mod_setenvif.c>
    SetEnvIfNoCase User-Agent "^$" bad_bot
    SetEnvIfNoCase User-Agent "wget" bad_bot
    SetEnvIfNoCase User-Agent "curl" bad_bot
    SetEnvIfNoCase User-Agent "HTTrack" bad_bot
    
    <Limit GET POST HEAD>
        Order Allow,Deny
        Allow from all
        Deny from env=bad_bot
    </Limit>
</IfModule>
```

**Что не так с этим блоком.**

**Фильтрация SQL-инъекций по `QUERY_STRING`** — это имитация WAF, которая не останавливает настоящую атаку (обходится кодированием и регистром) и при этом ломает нормальные запросы. Поиск по сайту со словом «select», товар с «concat(» в названии, любой параметр, содержащий подстроку `_REQUEST`, — всё это получит 403. Защита от инъекций находится в коде, в подготовленных запросах, а не в регулярке на входе.

**Блокировка `curl` и `wget` по User-Agent** — самый вредный пункт списка. Настоящий сканер подставит `Mozilla/5.0` первой же строкой конфига. А под запрет попадёте вы сами: мониторинг доступности, health-check, вебхуки платёжных систем и служб доставки, интеграции по API, ваш собственный `curl -I` для проверки редиректов. Разбор инцидента «платежи перестали подтверждаться» с такой строкой в `.htaccess` занимает часы, потому что искать причину идут в код оплаты.

**Блокировка пустого User-Agent** — по тем же причинам: часть легитимных серверных клиентов его не отправляет.

Что действительно работает вместо этого: ограничение частоты запросов на уровне nginx или Apache, актуальные версии CMS и модулей, и — если нужен именно WAF — отдельный инструмент вроде ModSecurity с поддерживаемым набором правил, а не десять строк регулярок.

## Полная конфигурация для production

```apache
# ============================================
# .htaccess для 1С-Битрикс
# ============================================

# Кодировка
AddDefaultCharset utf-8

# Безопасность
Options -Indexes -IncludesNoExec +FollowSymLinks
php_flag display_errors off

<Files .htaccess>
    Order allow,deny
    Deny from all
</Files>

# ============================================
# Редиректы и ЧПУ
# ============================================
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    
    # HTTPS
    RewriteCond %{HTTPS} off
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
    
    # www -> без www
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
    
    # Удаление index.php
    RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
    RewriteRule ^(.*)index\.php$ /$1 [R=301,L]
    
    # Trailing slash
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !/$
    RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]{1,5}$
    RewriteRule ^(.*)$ $1/ [R=301,L]
    
    # ЧПУ Битрикс
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
</IfModule>

# ============================================
# Сжатие
# ============================================
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/xml
    AddOutputFilterByType DEFLATE text/css text/javascript
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE application/xml image/svg+xml
</IfModule>

# ============================================
# Кэширование
# ============================================
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    ExpiresByType text/html "access plus 0 seconds"
    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 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
```

**Год кэширования для CSS и JS требует версионирования.** `ExpiresByType text/css "access plus 1 year"` означает, что браузер вернувшегося пользователя не станет перезапрашивать файл — со всеми последствиями после выкладки новой вёрстки. Работает это только если в адресе файла меняется что-то при каждом изменении содержимого: `style.css?v=hash` или имя с хэшем. Собственные CSS и JS шаблона такого версионирования обычно не имеют — для них год слишком много, разумнее месяц или явный параметр версии в шаблоне.

## Итоги

Здоровый `.htaccess` для Битрикса — это редиректы (по одному правилу на каждый вид дублей), правило ЧПУ и, если запросы до Apache действительно доходят, сжатие с кэшированием. Всё остальное, что обычно в нём лежит, стоит пересмотреть.

Порядок работы, который экономит время:

1. **Убедитесь, что файл вообще применяется.** На связке nginx + Apache половина правил не работает для статики.
2. **Проверяйте цепочки редиректов**, а не отдельные правила: `curl -sIL`.
3. **После правки — сразу в `error.log` Apache.** Три четверти пятисоток по теме объясняются одной строкой в логе.
4. **Не держите «защиту» из регулярок.** Она не останавливает атакующего и ломает свои же интеграции.
5. **Если есть доступ к конфигу виртуального хоста — переносите правила туда.** Быстрее и не читается на каждый запрос.

**Перед выкладкой** сохраните работающую копию файла рядом (`.htaccess.bak`) и проверьте результат из другого браузера или приватного окна — кэш редиректов на стороне браузера сам по себе способен убедить вас в том, что правило работает не так, как есть на самом деле. `curl` от этого свободен, поэтому проверять лучше им.