Справочник

.htaccess в nginx: куда перенести правила и как их переписать

nginx не читает файлы .htaccess: правила из них на сайте с nginx ничего не делают. Их переносят в файл настроек сайта: для переадресаций, запретов, пароля, кэша и сжатия в nginx есть свои строки, а после правки настройки проверяют и применяют двумя командами.

≈ 11 мин чтения
Содержание 14

Что сделать прямо сейчас

  1. Не удаляйте старый .htaccess, пока не перенесёте все правила: по нему удобно сверяться. Доступ к нему закройте — как.
  2. Команды вводятся на сервере: подключитесь к нему по SSH ([как подключиться](/instrukcii/kak-podklyuchitsya-k-vps-po-ssh/)) и набирайте их в том же окне. Откройте файл сайта: sudo nano /etc/nginx/sites-available/example.com. Вместо example.com — имя файла вашего сайта: список покажет ls /etc/nginx/sites-enabled/. Если система спросит пароль, введите пароль своего пользователя на сервере. Символы при вводе не видны — наберите пароль и нажмите Enter.
  3. Перепишите строки из .htaccess по таблице и впишите их внутрь блока server вашего сайта.
  4. Сохраните файл — Ctrl+O, Enter, затем Ctrl+X — и проверьте настройки: sudo nginx -t. В ответе должны быть слова syntax is ok и test is successful. Тогда примените их: sudo systemctl reload nginx. Если проверка нашла ошибку, nginx назовёт файл и номер строки, а сайт продолжит работать на старых настройках. Что значит сообщение — Все ошибки nginx.
  5. Проверьте результат через curl — как.

Почему nginx не видит .htaccess

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

Эта страница — для своего VPS с nginx, например настроенного по инструкции Как разместить сайт на VPS. Если сайт на виртуальном хостинге и правила не действуют, начните со статьи Почему .htaccess не работает.

Где писать правила

  • Правила для всего сайта — внутри блока server, в строке server_name которого стоит ваш домен. Если сайт работает по HTTPS, это блок со строкой listen 443 ssl — как устроены блоки.
  • Правила для одной папки — в блоке location ^~ /папка/. Знаки ^~ нужны, чтобы правила действовали и на файлы .php в этой папке: без них такие адреса уйдут в общий блок для PHP — как nginx выбирает блок. Чтобы PHP в папке работал, внутрь вкладывают свой блок для PHP — пример в разделе Доступ и пароль.
  • Если .htaccess лежал во вложенной папке, его строки переносят в блок location этой папки: отдельных файлов для папок у nginx нет.

Какая строка чем заменяется

В .htaccessВ nginxПодробнее
Redirect 301return 301 в блоке locationпереадресации
RewriteRule с флагом R=301rewrite с флагом permanentпереадресации
переадресация на HTTPSотдельный блок server для порта 80 с return 301301 в nginx
переадресация с www или на wwwотдельный блок serverадрес с www
условия !-f и !-d и правило на index.phptry_filesсайт на PHP
ErrorDocument 404error_page 404своя страница 404
Require all denieddeny allдоступ и пароль
Require ipallow и deny allдоступ и пароль
AuthType Basic и AuthUserFileauth_basic и auth_basic_user_fileпароль в nginx
ExpiresByTypeexpiresкэш в nginx
AddOutputFilterByType DEFLATEgzip и gzip_typesсжатие в nginx
Header setadd_headerзаголовки в nginx
Options -Indexesничего: список файлов в nginx выключен по умолчанию403 без индексного файла
DirectoryIndexindexстроки из Apache
php_value и php_flagфайл .user.ini или пул PHP-FPM.user.ini
RewriteEngine On и RewriteBaseничего: эти строки не нужны—

Переадресации

Одна страница

В .htaccess было:

Redirect 301 /old-page/ /new-page/

В nginx впишите внутрь блока server блок с точным адресом — знак равенства значит «ровно этот адрес»:

location = /old-page/ {
    return 301 /new-page/;
}

Раздел сайта со всеми страницами

В .htaccess было:

RewriteRule ^blog/(.*)$ /stati/$1 [R=301,L]

В nginx — строка rewrite внутри блока server:

rewrite ^/blog/(.*)$ /stati/$1 permanent;

В nginx путь в шаблоне начинается с косой черты, в отличие от RewriteRule в .htaccess. Флаг permanent даёт переадресацию 301, флаг redirect — 302. Переадресация с http:// на https:// разобрана в статье 301 Moved Permanently.

Адрес с www — без if

В .htaccess переадресацию с www делают условием RewriteCond по имени сайта. В nginx то же можно записать через if, но документация nginx называет такой способ неправильным, громоздким и неэффективным. Правильно — отдельный блок server для адреса с www:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

Вставьте этот блок в конец того же файла, после закрывающей скобки последнего блока server, а в строке server_name главного блока оставьте только example.com. Сертификат должен включать оба имени — с www и без: так его выпускает команда Certbot из инструкции Как разместить сайт на VPS. Все шаги — в разделе Оставьте один адрес: с www или без.

Доступ и пароль

Закрыть папку целиком

Вместо Require all denied в .htaccess папки впишите внутрь блока server:

location ^~ /private/ {
    deny all;
}

Вместо private — имя вашей папки. На любой адрес из неё nginx ответит 403.

Пустить только свой IP

Правила allow и deny nginx проверяет по порядку до первого совпадения, поэтому allow пишут выше строки deny all. Чтобы в папке работали файлы PHP, внутрь вкладывают блок для PHP:

location ^~ /admin/ {
    allow 203.0.113.10;
    deny all;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Строки include и fastcgi_pass скопируйте из блока location ~ \.php$ в том же файле: версия PHP в пути может быть другой. Вместо 203.0.113.10 укажите свой IP-адрес — с других адресов nginx ответит 403.

Пароль

Строки AuthType Basic и AuthUserFile в nginx заменяют auth_basic и auth_basic_user_file. Файл с паролями для nginx создайте по шагам из статьи Ошибка 401 Unauthorized, а блок для папки — по шагу 3 той же статьи: в нём тоже есть вложенный блок для PHP.

Кэш, сжатие и заголовки

Сроки в nginx записывают по-своему, поэтому не переносите их из .htaccess как есть — берите значения из примеров по ссылкам.

Сайт на PHP: все адреса в index.php

В .htaccess сайта на PHP стоит блок, который отправляет в index.php все адреса, кроме существующих файлов и папок:

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

В nginx его заменяет одна строка try_files. Если в файле сайта уже есть блок location /, поменяйте строку try_files в нём, а если блока нет, впишите его внутрь блока server:

location / {
    try_files $uri $uri/ /index.php?$args;
}

nginx ищет файл с таким именем, затем папку, а если нет ни того ни другого, передаёт запрос в index.php. Сам index.php выполняет блок location ~ \.php$ — как подключить PHP. Для WordPress нужна эта же строка: так работают постоянные ссылки. Если сайт без PHP, строка другая — готовые строки.

Закройте старые файлы .htaccess

Если в папке сайта остались файлы .htaccess и .htpasswd, nginx отдаст их по прямому адресу, а в .htpasswd лежат логины и зашифрованные пароли. Закройте такие файлы строками внутри блока server:

location ~ /\.ht {
    deny all;
}

Блок закрывает все файлы, имя которых начинается с .ht. Такой же блок есть в файле default из пакета nginx в Ubuntu: там он закомментирован и нужен, если у nginx и Apache одна папка сайта.

Как проверить

В терминале компьютера (как открыть терминал, про curl) запросите старый адрес с переадресацией:

curl -I https://example.com/old-page/

В ответе должны быть код 301 и строка Location с новым адресом; curl может показать Location маленькими буквами. Проверьте и запрет на служебные файлы:

curl -I https://example.com/.htaccess

Ответ 403 — файл закрыт. curl не запоминает переадресации, а браузер ответ 301 запоминает: если curl показывает новое, а браузер старое, очистите кэш браузера.

Ошибки и как их исправить

Что видитеЧто делать
nginx -t пишет unknown directiveв файл попала строка из .htaccess: замените её по таблице — разбор ошибки
is not allowed hereстрока стоит не в том блоке — разбор ошибки
unexpected end of file или unexpected "}"не хватает фигурной скобки или есть лишняя — разбор ошибки
directive is not terminated by ";"в конце строки нет точки с запятой — разбор ошибки
ERR_TOO_MANY_REDIRECTSпереадресации по кругу — разбор ошибки
открывается только главная, остальные страницы — 404нет строки try_files с index.php — как заменить
файлы .php в закрытой папке не выполняютсяв блоке location ^~ нет вложенного блока для PHP — пример
правило не действует, ошибок нетпроверьте, что выполнена команда reload и строка стоит в блоке server с вашим доменом в server_name, затем проверьте через curl

Источники

Сверено 15 октября 2026 года.

Что почитать дальше