Главная / База знаний / Миграция с Apache на Nginx: пошаговый план
инструкция · 22 октября 2026

Миграция с Apache на Nginx: пошаговый план

Разбираем, зачем и как переносить сайт с Apache на Nginx: перевод правил .htaccess в основной конфиг, замену mod_php на PHP-FPM и безопасный план переключения без простоя.

Зачем вообще мигрировать с Apache на Nginx

Решение о миграции обычно созревает не из абстрактного желания «быть современнее», а из конкретной практической причины: растущая посещаемость сайта, которую текущая конфигурация Apache на классическом prefork MPM начинает обслуживать с заметными задержками в часы пиковой нагрузки, или желание снизить потребление оперативной памяти на том же VPS без покупки более мощной конфигурации.

Событийная архитектура Nginx обрабатывает тысячи одновременных соединений заметно эффективнее по памяти, чем классическая модель Apache с отдельным процессом или потоком на каждое соединение, — это особенно заметно на сайтах с большим числом одновременных посетителей, длинными keep-alive соединениями или интенсивной раздачей статических файлов вроде изображений и файлов для скачивания. Подробное сравнение архитектурных различий обоих веб-серверов и того, когда разница действительно ощутима на практике, разобрано в отдельной статье базы знаний.

Другая частая причина миграции — переход на более современный и производительный стек обработки PHP через PHP-FPM вместо устаревающего mod_php, который исторически тянет за собой именно Apache как единственный практический вариант его использования на большинстве готовых сборок хостинг-панелей.

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

Главное препятствие: .htaccess не работает в Nginx вообще

Самое важное, что нужно понять перед началом миграции: Nginx не поддерживает файлы .htaccess ни в каком виде и никогда не будет их поддерживать — это не недоработка или отсутствующая опция, включаемая настройкой, а фундаментальная архитектурная особенность сервера. У Nginx попросту нет механизма «переопределения конфигурации на уровне директории», который Apache реализует через AllowOverride и чтение .htaccess-файлов на каждом шаге пути к запрошенному файлу.

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

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

Таблица соответствия: переводим директивы Apache в Nginx

RewriteRule — самая частая директива в реальных .htaccess-файлах, отвечающая за переписывание URL, — в Nginx её эквивалент задаётся директивой rewrite внутри блока location или server с похожим синтаксисом регулярных выражений, но с другим порядком аргументов и флагов.

Перевод правила RewriteRule Apache в эквивалентную директиву rewrite Nginx
# Apache (.htaccess)
RewriteEngine On
RewriteRule ^product/([0-9]+)$ product.php?id=$1 [L,QSA]

# Nginx (server-блок)
rewrite ^/product/([0-9]+)$ /product.php?id=$1 last;

Redirect и RedirectMatch, используемые для простых постоянных или временных редиректов, в Nginx заменяются директивой return с явным HTTP-кодом ответа — это даже проще и нагляднее по синтаксису, чем оригинальные Apache-директивы.

Перевод постоянного редиректа Apache в директиву return Nginx
# Apache (.htaccess)
Redirect 301 /old-page.html /new-page.html

# Nginx (server-блок)
location = /old-page.html {
    return 301 /new-page.html;
}

Header set из модуля mod_headers, часто использующийся для добавления заголовков безопасности или кэширования, в Nginx переносится директивой add_header — с важной оговоркой, что add_header в Nginx не наследуется автоматически при указании этой же директивы на более специфичном уровне вложенности, если там уже есть хотя бы один свой add_header, что часто становится неожиданностью при переносе.

Перевод заголовка безопасности из mod_headers в add_header Nginx
# Apache (.htaccess)
Header set X-Frame-Options "SAMEORIGIN"

# Nginx (server-блок)
add_header X-Frame-Options "SAMEORIGIN" always;

Deny from, ограничивающая доступ по IP-адресу в классическом синтаксисе Apache, в Nginx заменяется парой директив allow и deny внутри нужного location — синтаксис отличается порядком проверки правил, поэтому при переносе важно сохранить логику «сначала явные разрешения, затем общий запрет», а не просто переставить директивы механически.

Перевод ограничения доступа по IP из классического синтаксиса Apache в Nginx
# Apache (.htaccess)
Order allow,deny
Deny from all
Allow from 203.0.113.10

# Nginx (location-блок)
allow 203.0.113.10;
deny all;

Обработка PHP: переход с mod_php на PHP-FPM

Помимо перевода правил .htaccess, второе крупное структурное изменение при миграции — способ исполнения PHP-кода. Nginx физически не умеет исполнять PHP самостоятельно, в отличие от Apache с mod_php, где интерпретатор встроен прямо в процесс веб-сервера, — вместо этого все PHP-запросы обязательно передаются отдельному процессу PHP-FPM через сокет или сетевой порт по протоколу FastCGI.

Хорошая новость в том, что тот же самый код приложения на PHP работает без единого изменения независимо от способа его исполнения — mod_php или PHP-FPM для самого кода абсолютно прозрачны, различается только конфигурация веб-сервера вокруг него. Установка PHP-FPM обычно сводится к добавлению одного дополнительного пакета к уже установленной версии PHP.

Установка и запуск PHP-FPM для уже используемой версии PHP
apt install php8.3-fpm -y
systemctl enable --now php8.3-fpm

Подробная пошаговая настройка самой связки Nginx с PHP-FPM — конфигурация пула процессов, выбор режима pm, таймауты, диагностика ошибки 502 Bad Gateway — разобрана в отдельной статье базы знаний, к которой стоит обратиться перед миграцией, если этот стек ещё не знаком по опыту.

При переносе важно перепроверить лимиты PHP, ранее заданные в .htaccess через директивы вроде php_value upload_max_filesize, которые Nginx тоже не поддерживает, — их нужно перенести либо в глобальный php.ini, либо точечно в конфигурацию конкретного пула PHP-FPM через php_admin_value, иначе загрузка файлов или другие операции, зависящие от этих лимитов, начнут неожиданно давать сбой сразу после переключения на новый стек.

Собираем полный server-блок для типичного сайта на PHP

После перевода всех правил из .htaccess и настройки PHP-FPM итоговый server-блок для типичного сайта на PHP-CMS объединяет все рассмотренные выше элементы в одну целостную конфигурацию, заменяющую и основной VirtualHost Apache, и все накопленные годами файлы .htaccess.

Итоговый server-блок Nginx, объединяющий перенесённые правила ЧПУ, PHP-FPM, кэширование статики и редирект
server {
    listen 80;
    server_name example.ru www.example.ru;
    root /var/www/example.ru/public;
    index index.php;

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~* \.(jpg|jpeg|png|gif|css|js)$ {
        expires 30d;
        add_header Cache-Control "public";
    }

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

    location ~ /\.ht {
        deny all;
    }
}

Такой конфиг стоит собирать и проверять постепенно, добавляя перенесённые блоки правил один за другим и перепроверяя синтаксис командой nginx -t после каждого существенного изменения, а не пытаться сразу написать весь файл целиком по памяти и обнаружить единственную опечатку только после реального переключения на продакшене.

Безопасный план миграции без риска простоя

Первый шаг безопасной миграции — развернуть новый Nginx полностью параллельно работающему Apache, не трогая продакшен-трафик вовсе: либо на отдельном тестовом порту того же сервера (например, 8080), либо на отдельном staging-поддомене с той же копией кода и базы данных, чтобы иметь возможность полноценно протестировать все критичные страницы сайта без риска для реальных посетителей.

Временный тестовый порт для проверки конфигурации Nginx параллельно с рабочим Apache
server {
    listen 8080;
    server_name example.ru;
    # тот же конфиг для тестирования параллельно с рабочим Apache на 80 порту
}

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

Третий шаг — только после уверенного прохождения всех тестов на staging-окружении переключить реальный трафик: либо остановить Apache и перевести Nginx на стандартные 80 и 443 порты того же сервера, либо, при миграции на новый сервер целиком, изменить DNS-записи домена, указав их на новый IP-адрес с уже настроенным и протестированным Nginx. Подробный процесс переноса сайта на новый сервер, включая перенос базы данных и файлов, разобран в отдельной статье про миграцию сайта.

Четвёртый шаг — держать конфигурацию Apache и его VirtualHost неудалёнными и готовыми к быстрому обратному переключению в течение нескольких дней после перехода, на случай если после реального продакшен-трафика обнаружится забытое правило или редкий сценарий использования, не покрытый тестированием на staging-этапе. Только убедившись в полной стабильности работы нового стека на реальной нагрузке, имеет смысл окончательно удалять Apache и освобождать занимаемые им ресурсы.

Что может пойти не так и как это диагностировать

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

Отслеживание в реальном времени страниц, возвращающих 404 после миграции
tail -f /var/log/nginx/example.ru-error.log | grep 404

Вторая типичная проблема — ошибка 502 Bad Gateway, почти всегда связанная с неверным путём к сокету PHP-FPM в конфигурации Nginx, не совпадающим с реальным путём в конфигурации пула, или с недостаточным значением pm.max_children для новой нагрузки, — подробная диагностика этой конкретной ошибки разобрана в статье про настройку связки Nginx и PHP-FPM.

Третья проблема — заголовки безопасности или кэширования, ранее заданные через mod_headers в .htaccess, оказываются утеряны при переносе, что не вызывает явной ошибки на сайте, но снижает оценку безопасности при последующем аудите или ухудшает поведение кэширования статики в браузерах посетителей — стоит явно сверить полный список заголовков, отдаваемых сайтом до и после миграции, инструментами вроде curl -I.

Проверка HTTP-заголовков, отдаваемых сервером, до и после переключения на Nginx
curl -I https://example.ru/

Проверка производительности после миграции

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

Нагрузочный тест: 1000 запросов с 50 одновременными соединениями через Apache Bench
ab -n 1000 -c 50 https://example.ru/

Утилита ab (Apache Bench, несмотря на название, прекрасно работает с любым веб-сервером) или более современная альтернатива wrk позволяют сравнить среднее время ответа и число обработанных запросов в секунду до и после миграции при одинаковом профиле нагрузки — сравнение стоит проводить в одинаковых условиях, желательно в период низкой реальной посещаемости сайта, чтобы синтетический тест не накладывался на живой трафик и не искажал показания друг друга.

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

Чек-лист миграции с Apache на Nginx

Шаг 1. Соберите и построчно проаудируйте все существующие .htaccess-файлы сайта, включая вложенные поддиректории, а не только корневой файл.

Шаг 2. Переведите каждую директиву в эквивалентный синтаксис Nginx: RewriteRule → rewrite, Redirect → return, Header set → add_header, Deny from → allow/deny.

Шаг 3. Установите PHP-FPM для используемой версии PHP и перенесите php_value-лимиты из .htaccess в конфигурацию пула через php_admin_value.

Шаг 4. Разверните новый Nginx-конфиг на тестовом порту или staging-домене параллельно с рабочим Apache и вручную протестируйте все критичные страницы и формы сайта.

Шаг 5. Проверьте синтаксис итогового конфига командой nginx -t и явно сверьте список HTTP-заголовков и работающих редиректов до и после переключения.

Шаг 6. Переключите реальный трафик на Nginx, оставив Apache неудалённым в течение нескольких дней на случай необходимости быстрого отката.

Шаг 7. После подтверждённой стабильной работы на реальной нагрузке удалите Apache и освободите занимаемые им ресурсы сервера.

Итог: трудоёмко один раз, но окупается на растущей нагрузке

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

Результат обычно оправдывает затраченное время для проектов с растущей посещаемостью или планами масштабирования — более эффективная событийная архитектура Nginx и разделение статики от обработки PHP через PHP-FPM снимают целый класс проблем с производительностью, которые на Apache с mod_php проявились бы заметно раньше при том же росте трафика.

Если миграция кажется рискованной задачей для сайта, который нельзя останавливать даже на короткое время, — оставьте заявку внизу страницы, поможем спланировать и провести перенос на Nginx с тестированием на staging-окружении и безопасным переключением без простоя для реальных посетителей сайта.

почему мы

Почему стоит выбрать нас

Быстрый запуск

Подберём конфигурацию и развернём проект в день обращения.

Надёжность

NVMe-диски, защита от DDoS и резервные копии по расписанию.

Поддержка 24/7

Дежурные инженеры на связи в любое время суток.

Настройка под ключ

Установим CMS, настроим веб-сервер, SSL и почту за вас.

Перенос без простоя

Аккуратно перенесём сайт и базу данных на новый сервер.

Прозрачные цены

Актуальные тарифы и честный подбор без навязывания.

частые вопросы

Вопросы и ответы

Обязательно ли переносить весь сайт сразу целиком?

Нет, распространённая и более безопасная практика — временная гибридная схема, где Nginx работает на внешних портах как reverse proxy и постепенно забирает на себя обработку статики, пока Apache ещё продолжает обрабатывать динамические запросы, что снижает риск на время миграции.

Что делать, если в проекте используются сторонние Apache-модули, для которых нет аналога в Nginx?

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

Как проверить корректность нового конфига Nginx перед реальным переключением?

Командой nginx -t, которая проверяет синтаксис всех конфигурационных файлов и покажет конкретную строку с ошибкой, если она есть, — обязательный шаг перед каждым перезапуском или перезагрузкой конфигурации в продакшене.

Что произойдёт с закладками и внешними ссылками на старые URL после миграции?

Если структура URL не менялась, а .htaccess-редиректы корректно перенесены в конфигурацию Nginx через директиву return или rewrite, внешние ссылки продолжат работать без изменений — проблема возникает только при потере части правил редиректов в процессе переноса.

Можно ли использовать Nginx и Apache на одном сервере одновременно постоянно, а не только на время миграции?

Да, это устоявшаяся практика — Nginx на внешних портах отдаёт статику и терминирует SSL, а Apache на внутреннем порту исполняет специфичную логику; многие проекты сознательно остаются на такой гибридной схеме на постоянной основе, а не только как промежуточный этап миграции.

Нужно ли менять версию PHP при переходе с mod_php на PHP-FPM?

Не обязательно — тот же установленный пакет PHP той же версии можно использовать через PHP-FPM вместо mod_php, потребуется лишь установить дополнительный пакет php-fpm и настроить пул процессов, тогда как сам код приложения останется без изменений.

Как убедиться, что все правила из .htaccess перенесены и ничего не забыто?

Стоит явно пройтись по каждой директиве в исходном .htaccess построчно и найти для неё соответствие в новом конфиге Nginx, а затем протестировать все критичные URL сайта (главную страницу, товарные карточки, форму обратной связи, admin-панель) вручную на staging-окружении перед переключением production-трафика.

Как оплачивать услуги?

Оплата помесячная, для облачных серверов доступна почасовая тарификация. Принимаются карты, банковские переводы и электронные кошельки.

Есть ли круглосуточная поддержка?

Да, дежурные инженеры на связи 24/7.

Выдаёте ли закрывающие документы?

Да, предоставим необходимые документы для оплаты.

Как оставить заявку?

Заполните форму на странице или нажмите «Заказать» — мы свяжемся и поможем с подбором.

заявка

Оставьте заявку

Ответим и поможем с подбором и настройкой.