Сайт работает по HTTP, но не открывается по HTTPS после переноса
После переноса сайта ситуация может выглядеть странно: http://example.com уже открывается с нового сервера, а https://example.com выдаёт ошибку соединения, предупреждение о сертификате, бесконечный редирект или вообще показывает другой сайт. Сам факт работы HTTP почти ничего не говорит о состоянии HTTPS.
HTTP и HTTPS используют разные порты и могут обслуживаться разными конфигурациями Nginx или Apache. Порт 80 может быть открыт, а 443 закрыт. HTTPS virtual host может отсутствовать. Сертификат может быть установлен на сервере, но веб-сервер отдаёт сертификат соседнего домена. При Cloudflare добавляется ещё одно соединение между CDN и origin-сервером.

Поэтому начинать с повторного выпуска Let’s Encrypt, очистки кеша WordPress или изменения siteurl — плохой маршрут. Сначала нужно определить, где именно обрывается запрос: DNS, TCP-соединение с 443, TLS handshake, выбор virtual host, сертификат, proxy, редирект или уже сама CMS.
Рабочий порядок диагностики: DNS и IP → TCP/443 → Nginx или Apache → HTTPS virtual host → сертификат и цепочка → Cloudflare или reverse proxy → редиректы → WordPress. Если нижний уровень не работает, настройки верхнего пока лучше не трогать.
Что именно означает «HTTP работает, а HTTPS не открывается»
Первое действие — зафиксировать точный симптом. Фраза «не работает SSL» слишком широкая: в одном случае клиент вообще не подключается к 443, в другом TLS уже работает, но сервер отдаёт чужой сертификат, а в третьем HTTPS успешно принят и проблема начинается только на уровне WordPress или PHP-FPM.
Откройте HTTP и HTTPS отдельно, а затем сравните ответы:
curl -I http://example.com/
curl -Iv https://example.com/
Ключ -v показывает выбранный IP, попытку TCP-соединения, TLS handshake, сведения о сертификате и HTTP-ответ. Если в выводе появляется что-то вроде:
Failed to connect to example.com port 443
до проверки сертификата запрос ещё не дошёл. И наоборот: если curl уже показывает сертификат и затем получает HTTP/2 404 или HTTP/1.1 502 Bad Gateway, сеть и TLS находятся ниже реальной проблемы.
| Симптом | Где искать причину | Первая проверка | Что пока не делать |
|---|---|---|---|
| ERR_CONNECTION_REFUSED | Порт 443, сервис, firewall | ss, nc, curl |
Не перевыпускать сертификат |
| ERR_CONNECTION_TIMED_OUT | Маршрут, firewall, DNS, security group | Проверить IP и 443 извне | Не менять WordPress |
| ERR_SSL_PROTOCOL_ERROR | TLS-конфигурация или неправильный сервис на 443 | curl -Iv, openssl s_client |
Не ограничиваться сроком сертификата |
| ERR_CERT_COMMON_NAME_INVALID | SNI, virtual host, сертификат | openssl s_client |
Не чистить кеш CMS |
| Открывается другой сайт | HTTPS virtual host | nginx -T или apachectl -S |
Не менять DNS без подтверждения |
| ERR_TOO_MANY_REDIRECTS | Nginx, Apache, Cloudflare, WordPress | curl -IL |
Не переустанавливать SSL |
| Mixed Content | WordPress, тема, плагины, база | DevTools Console | Не менять firewall |
Если TCP-соединение не установилось, до TLS запрос ещё не дошёл. Если TLS handshake проходит, но имя в сертификате не совпадает с доменом, порт и сеть уже работают. Если сертификат принимается и сервер возвращает HTTP-код, искать нужно ещё выше.
Сначала определяем точку разрыва. Это сразу отсекает половину лишних действий.
Указывает ли домен на тот сервер, куда был перенесён сайт
После переноса нужно доказать, что запрос отправляется именно на новый сервер. Работающий HTTP не всегда закрывает этот вопрос: www и домен без www могут иметь разные записи, IPv4 и IPv6 — разные адреса, а Cloudflare может скрывать origin за своими IP.
Как проверить A и AAAA после переноса
Сначала посмотрите IPv4:
dig +short example.com A
dig +short www.example.com A
Затем IPv6:
dig +short example.com AAAA
dig +short www.example.com AAAA
Если dig недоступен:
nslookup example.com
Типичная ситуация после миграции выглядит так: A-запись уже изменена, сайт по IPv4 открывается с нового VPS, но AAAA всё ещё содержит IPv6 старого сервера. На компьютере без IPv6 всё работает, а другой пользователь получает старый сертификат или старую версию сайта.
Проверить пути отдельно можно через curl:
curl -4Iv https://example.com/
curl -6Iv https://example.com/
Если curl -4 работает, а curl -6 подключается к другому адресу или завершается ошибкой, проблема локализована довольно точно. Проверяйте AAAA, IPv6 listener и firewall для IPv6.
Не удаляйте AAAA автоматически. Если IPv6 действительно используется на новом сервере, запись нужна. Исправлять следует адрес или серверную конфигурацию, а не отключать протокол только ради исчезновения симптома.
Как проверить новый сервер без изменения DNS
curl --resolve позволяет отправить HTTPS-запрос на конкретный IP, сохранив правильные Host и TLS SNI:
curl -Iv --resolve example.com:443:203.0.113.10 https://example.com/
Замените 203.0.113.10 на IP нового VPS. Если через --resolve HTTPS работает, а обычный запрос по домену нет, новый сервер уже способен обслуживать сайт. Значит, подозрение смещается в DNS, кеш resolver, CDN или proxy.
Этот же тест помогает, когда старый VPS ещё не отключён. Можно сравнить ответы старого и нового IP по одному и тому же доменному имени, не редактируя локальный файл hosts и не дожидаясь смены DNS.
Доступен ли порт 443 на новом VPS
Если HTTP открывается через 80, а HTTPS получает connection refused или timeout, проверяется TCP/443. Наличие работающего Nginx или Apache на 80 не означает, что сервер принимает HTTPS.
На VPS выполните:
ss -lntp | grep ':443'
Нормальный вывод может выглядеть примерно так:
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1842,fd=7))
Здесь видно сразу две вещи: порт находится в состоянии LISTEN и его обслуживает Nginx. Если команда ничего не возвращает, на 443 никто не слушает. Если порт занят другим процессом, это тоже повод остановиться и выяснить, что именно принимает соединения:
ss -lntp
Иногда после изменения схемы сервера 443 оказывается занят старым proxy, контейнером или другим веб-сервисом. Внешне порт открыт, но запрос попадает совсем не в тот Nginx, конфигурацию которого администратор сейчас редактирует.
После локальной проверки нужен тест извне:
nc -vz example.com 443
или:
curl -Iv https://example.com/
Connection refused обычно означает, что адрес достижим, но соединение отвергается: сервис не слушает 443 или firewall работает в режиме reject. Timeout чаще связан с drop, маршрутом, security group или недоступным IP. Это диагностический ориентир, а не универсальное правило.
Проверьте firewall тем инструментом, который реально используется:
ufw status
firewall-cmd --list-all
nft list ruleset
На VPS в облачной инфраструктуре может существовать ещё один firewall в панели провайдера. Linux показывает открытый 443, Nginx слушает порт, но внешний curl всё равно получает timeout. В такой ситуации надо проверять security group или сетевые ACL.
Если на 443 никто не слушает, сертификат пока ни при чём. Сначала нужно получить нормальное TCP-соединение.
После исправления снова выполните внешний curl -Iv. Если он дошёл до TLS handshake, сетевой уровень уже пройден.
Настроен ли HTTPS virtual host в Nginx или Apache
Порт 443 может быть открыт и обслуживаться веб-сервером, но нужного сайта на нём всё равно нет. После миграции нередко переносится HTTP-конфигурация, а HTTPS server block или VirtualHost *:443 остаётся на старой машине.
Проверка Nginx
Выведите фактическую конфигурацию Nginx:
nginx -T
Нужный домен должен присутствовать в server block, который слушает 443:
listen 443 ssl;
server_name example.com www.example.com;
При использовании IPv6 обычно нужен и соответствующий listener:
listen [::]:443 ssl;
Проверьте пути к сертификату и ключу, затем синтаксис:
nginx -t
Только после успешного теста конфигурацию перечитывают:
systemctl reload nginx
Если nginx -t сообщает об ошибке, сначала исправляется она. Не нужно делать reload и надеяться, что Nginx «возьмёт правильную часть» конфигурации.
Проверка Apache
В Apache полезно сразу посмотреть карту virtual hosts:
apachectl -S
Для нужного домена должен существовать HTTPS VirtualHost:
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
</VirtualHost>
Проверка синтаксиса:
apachectl configtest
Название команды или службы может различаться между дистрибутивами, но задача одна: установить, какой virtual host реально принимает запрос к нужному имени на 443.
| Уровень | Что должно работать | Чем проверить |
|---|---|---|
| DNS | Домен возвращает ожидаемый IP | dig, nslookup |
| TCP | 443 принимает соединение | ss, nc |
| TLS | Handshake завершается | curl -Iv, openssl s_client |
| SNI | Выбирается нужный virtual host | openssl, конфиг Nginx/Apache |
| Certificate | SAN соответствует имени домена | openssl x509 |
| HTTP | Сервер возвращает ожидаемый код | curl -I |
| Application | CMS корректно работает с HTTPS | WordPress, DevTools, логи |
Если 443 уже принимает соединения, но нужного домена нет в HTTPS-конфигурации, проблема найдена. Не нужно спускаться обратно к DNS или firewall.
Какой сертификат реально отдаёт сервер на 443
Смотреть только на файлы в /etc/letsencrypt/ недостаточно. На диске может лежать свежий сертификат нужного домена, а клиенту Nginx или Apache продолжает отдавать старый сертификат либо сертификат другого virtual host.
Проверьте сертификат, который реально приходит по сети:
openssl s_client -connect example.com:443 -servername example.com </dev/null
Параметр -servername передаёт SNI. Без него сервер с несколькими сайтами может показать сертификат default virtual host, и диагностика пойдёт в неправильную сторону.
Для компактного просмотра:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
Смотрите прежде всего на subjectAltName. Если сайт используется как example.com и www.example.com, сертификат должен покрывать оба имени либо соответствовать им другим допустимым способом.
| Поле | Что показывает | Что считать проблемой |
|---|---|---|
| SAN | Имена в сертификате | Нет текущего имени сайта |
| Issuer | Центр, подписавший сертификат | Неожиданный сертификат или CA |
| Not Before | Начало срока действия | Сертификат ещё не действует |
| Not After | Окончание срока действия | Срок уже закончился |
| SNI response | Какой сертификат выбран для имени | Возвращается сертификат соседнего сайта |
Certbot может уже обновить файлы, а Nginx всё ещё отдаёт старый сертификат, если конфигурация не была перечитана или HTTPS обслуживает другой server block. Поэтому после любого изменения проверяйте ответ по сети повторно.
Смотрим не сертификат «который должен работать», а тот, который реально прилетает клиенту.
Не потерялась ли полная цепочка SSL-сертификата после переноса
Если сертификат выпущен на правильный домен и не просрочен, но один клиент доверяет сайту, а другой сообщает об ошибке проверки, нужно проверить цепочку сертификатов. После ручного переноса здесь легко оставить только leaf certificate и забыть intermediate.
Посмотрите, что сервер действительно отдаёт:
openssl s_client -showcerts -connect example.com:443 -servername example.com </dev/null
Как понять вывод openssl s_client
Ближе к концу вывода openssl s_client есть результат проверки. Хороший ориентир:
Verify return code: 0 (ok)
Это означает, что OpenSSL на этой машине смог построить доверенную цепочку с использованием собственного хранилища доверенных CA. Результат зависит и от локального trust store клиента, поэтому одна команда не заменяет все возможные тесты, но для серверной диагностики это сильный критерий.
При проблеме могут появляться сообщения вроде:
unable to get local issuer certificate
или:
unable to verify the first certificate
| Результат OpenSSL | Что это означает | Что проверить |
|---|---|---|
Verify return code: 0 (ok) |
Цепочка успешно проверена этим клиентом | Если браузер всё ещё ругается, искать имя, срок, SNI или другой путь подключения |
unable to get local issuer certificate |
Клиент не смог найти сертификат издателя | Intermediate chain и файл, указанный в веб-сервере |
unable to verify the first certificate |
Переданной цепочки недостаточно для проверки | Bundle/fullchain и порядок сертификатов |
| Передаётся только один сертификат | Сервер может отдавать только leaf | Настройку цепочки в Nginx или Apache |
Для Let’s Encrypt в типичной конфигурации Nginx в ssl_certificate используется fullchain.pem, а приватный ключ задаётся отдельно:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
Названия файлов у другого CA могут отличаться. Не нужно механически искать fullchain.pem, если сертификат выпускался не Let’s Encrypt. Проверяется смысл: сервер должен передать достаточную цепочку.
Почему один браузер иногда открывает сайт, а другой нет? Клиенты используют разные хранилища доверия, могут иметь разные промежуточные сертификаты в кеше и по-разному строить цепочку. Именно поэтому фраза «у меня Chrome открыл» не доказывает, что сервер передаёт всё корректно.
После изменения bundle выполните syntax test веб-сервера, reload и снова запустите openssl s_client. Результат должен измениться на серверном ответе, а не только в файлах.
Почему Let’s Encrypt после переноса не выпускает сертификат
Если на старом сервере Let’s Encrypt продлевался нормально, а после смены IP Certbot получает validation error, повторять одну и ту же команду бессмысленно. ACME проверяет домен снаружи, поэтому сначала нужно найти, куда реально приходит challenge.
Проверьте A и AAAA, затем убедитесь, что HTTP-запрос попадает на новый сервер. Для HTTP-01 challenge сервер Let’s Encrypt должен получить проверочный ресурс через HTTP. Для DNS-01 логика другая, поэтому требование доступного 80 порта к нему напрямую не относится.
Посмотреть сертификаты, известные Certbot:
certbot certificates
Для уже настроенного renewal:
certbot renew --dry-run
--dry-run помогает проверить существующий механизм продления. Если сертификат на новом сервере ещё не выпущен, основная информация находится в ошибке конкретной ACME-проверки.
Что означает ошибка ACME challenge
| Симптом или ошибка | Что вероятнее всего произошло | Первая проверка |
|---|---|---|
unauthorized |
CA дошёл до домена, но получил неправильный challenge или ответ | Webroot, маршрут /.well-known/acme-challenge/, redirect, virtual host |
| Connection timeout | CA не может подключиться к серверу | A/AAAA, порт 80, firewall, security group |
NXDOMAIN |
Нужная DNS-запись не разрешается | DNS-зона и авторитетные NS |
| Challenge открывается со старого сайта | Запрос всё ещё приходит на старый VPS или кеширующий proxy | A/AAAA, CDN, DNS-кеш |
www проходит, а apex-домен нет |
Имена имеют разные DNS или virtual host | Проверить каждое имя отдельно |
Для HTTP-01 можно проверить сам маршрут вручную. Создайте тестовый файл именно в том webroot, который использует ACME-клиент, и убедитесь, что он доступен снаружи по ожидаемому URL. Если вместо файла приходит 301 на другой домен, 403, страница WordPress или ответ старого сервера, причина уже видна.
После миграции особенно полезно перепроверить:
- A и AAAA;
- доступность 80 для HTTP-01;
- правильный webroot;
/.well-known/acme-challenge/;- редиректы;
- Cloudflare или другой proxy;
- не продолжает ли старый VPS обслуживать одно из имён.
Не отключайте защиту сайта целиком ради Certbot. Сначала установите, какой именно challenge не проходит и какой ответ получает ACME-сервер.
Сначала чинится validation path. Потом повторяется выпуск сертификата.
Почему HTTPS открывает чужой сайт или неправильный сертификат
Представим VPS с тремя сайтами на одном IP. Для всех трёх HTTP server block настроены правильно, а HTTPS-конфигурацию после миграции создали только для двух. Третий домен приходит на 443, но собственного SSL virtual host для него нет — запрос забирает default-конфигурация. В браузере появляется соседний сайт или его сертификат.
Здесь TCP/443 уже работает. DNS тоже может быть совершенно правильным. Проверять нужно выбор virtual host по SNI.
Для Nginx:
nginx -T
Для Apache:
apachectl -S
Затем сравните один IP с разными именами:
curl -Iv --resolve example.com:443:203.0.113.10 https://example.com/
curl -Iv --resolve other-domain.com:443:203.0.113.10 https://other-domain.com/
Можно сравнить и сертификаты:
openssl s_client -connect 203.0.113.10:443 -servername example.com </dev/null
openssl s_client -connect 203.0.113.10:443 -servername other-domain.com </dev/null
Если оба имени получают один и тот же сертификат, хотя должны использовать разные virtual host, проверяйте server_name, ServerName, ServerAlias, порядок SSL vhost и default server.
Отдельно проверьте IPv6. Nginx может правильно обслуживать 0.0.0.0:443, но иметь другую конфигурацию для [::]:443. Тогда curl -4 получает правильный сайт, а curl -6 — соседний.
Порт живой. Сертификат тоже есть. Просто запрос забрал не тот сайт.
Не ломает ли HTTPS Cloudflare, CDN или reverse proxy
Когда домен проксируется через Cloudflare, HTTPS состоит уже как минимум из двух участков: браузер устанавливает TLS с Cloudflare, а Cloudflare отдельно соединяется с origin. Поэтому рабочий сертификат на edge ничего не говорит о состоянии TLS на самом VPS.
Сравните обычный запрос и origin:
curl -Iv https://example.com/
curl -Iv --resolve example.com:443:ORIGIN_IP https://example.com/
Если origin отвечает правильно, а через Cloudflare возникает ошибка, проблема расположена между CDN и origin либо в настройке Cloudflare. Если оба запроса ломаются одинаково, сначала чините сам VPS.
| Режим Cloudflare | Браузер → Cloudflare | Cloudflare → origin | Требование к origin |
|---|---|---|---|
| Flexible | HTTPS | HTTP | HTTPS на origin для этого режима не используется |
| Full | HTTPS | HTTPS | Origin должен принимать TLS |
| Full (strict) | HTTPS | HTTPS | Сертификат origin должен проходить строгую проверку |
Flexible после миграции способен создать цикл: Cloudflare приходит к VPS по HTTP, origin принудительно редиректит HTTP на HTTPS, а внешняя схема при этом уже HTTPS. В результате запрос ходит по кругу.
Коды Cloudflare тоже дают направление: 521 указывает на проблему соединения с origin или отказ сервера, 522 — на таймаут, 525 — на неудачный SSL handshake между Cloudflare и origin, 526 — на проверку сертификата origin в строгом режиме.
Есть пограничный случай: origin firewall разрешает 443 только с сетей Cloudflare. Тогда прямой curl --resolve с вашего компьютера может не пройти, хотя production-трафик через Cloudflare работает. Такой результат не доказывает поломку origin — сначала проверьте правила доступа.
У reverse proxy логика та же: нужно знать, где завершается TLS и какой протокол используется до backend. Не смешивайте внешний HTTPS с внутренним соединением proxy → приложение.
Не создают ли HTTP→HTTPS редиректы цикл после миграции
Если TLS handshake проходит и сертификат принимается, но браузер показывает ERR_TOO_MANY_REDIRECTS, сертификат можно оставить в покое. Запрос уже дошёл до HTTP-логики и зациклился там.
Проследите цепочку:
curl -IL http://example.com/
curl -IL https://example.com/
Смотрите не только коды 301, 302, 307, 308, но и каждый Location. Например:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
HTTP/2 301
Location: http://example.com/
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Здесь причина очевидна: один уровень переводит HTTP на HTTPS, а другой возвращает HTTPS обратно на HTTP.
После переноса одновременно могут работать:
- redirect в Nginx;
- правила Apache;
.htaccess;- WordPress;
- SSL-плагин;
- Cloudflare;
- reverse proxy;
- редирект между
wwwи доменом безwww.
За reverse proxy отдельно проверяется определение исходной схемы. Backend может получать обычный HTTP от proxy, хотя посетитель пришёл по HTTPS. Для передачи исходной схемы часто используется X-Forwarded-Proto.
Если backend слушает локально и обслуживает несколько сайтов, тест лучше выполнять с Host:
curl -I \
-H 'Host: example.com' \
-H 'X-Forwarded-Proto: https' \
http://127.0.0.1/
Без Host: example.com запрос к 127.0.0.1 может попасть в default virtual host, и результат не будет относиться к нужному сайту.
Такой тест корректен только с учётом реальной архитектуры proxy. Не нужно добавлять X-Forwarded-Proto в WordPress или Nginx просто потому, что он встретился в инструкции.
Если curl -IL показывает повтор одного и того же набора URL, сначала найдите уровень, который формирует обратный Location. Иначе можно бесконечно менять правила на другом уровне.
После изменения снова выполните curl -IL. Нормальная цепочка должна закончиться конечным ответом, а не вернуться к уже посещённому URL.
Что проверить в WordPress после восстановления HTTPS на сервере
К WordPress стоит переходить только после того, как серверный HTTPS уже работает. Если curl получает нормальный TLS-ответ и правильный сертификат, но CMS редиректит на HTTP, ломает /wp-admin/ или продолжает загружать ресурсы через HTTP, проблема находится выше TLS.
WordPress отправляет обратно на HTTP
Проверьте home и siteurl. При наличии WP-CLI:
wp option get home
wp option get siteurl
После окончательного перехода на HTTPS обычно ожидаются значения:
https://example.com
Те же параметры хранятся в wp_options, если не переопределены через wp-config.php. Проверьте также:
WP_HOME
WP_SITEURL
Если WordPress работает за reverse proxy, приложение должно правильно определять исходную HTTPS-схему. При обработке HTTP_X_FORWARDED_PROTO учитывайте доверие к proxy: принимать такой заголовок безусловно от любого клиента — плохая идея.
Если статический файл по HTTPS открывается нормально, а WordPress продолжает отдавать 301 на HTTP, сеть, 443 и сертификат уже не главные подозреваемые. Запрос дошёл до приложения. Ищем выше.
HTTPS работает, но браузер показывает mixed content
Mixed content означает, что HTML загружен по HTTPS, но отдельные изображения, CSS, JavaScript, шрифты или API всё ещё вызываются через http://.
Откройте DevTools → Console и Network. Браузер обычно показывает конкретный небезопасный URL.
Источник может находиться в:
- старых абсолютных URL в базе WordPress;
- настройках темы;
- Elementor или другом конструкторе;
- CSS;
- плагинах;
- вручную вставленном HTML;
- внешних скриптах.
Не запускайте глобальный search-replace базы без backup. WordPress хранит в базе не только обычные строки, поэтому для массовой замены лучше использовать инструменты, которые корректно работают со структурой данных, например WP-CLI.
После исправления перезагрузите страницу без кеша и снова проверьте Console и Network. Главная страница без предупреждений ещё не гарантирует, что старые HTTP URL не остались в других шаблонах.
Какие логи смотреть, если внешне всё настроено правильно
Если DNS правильный, 443 открыт, сертификат выглядит нормально, а HTTPS всё ещё ведёт себя странно, откройте журнал и воспроизведите один запрос. Один свежий запрос обычно полезнее тысячи старых строк.
Для Nginx:
tail -f /var/log/nginx/error.log
Во втором терминале:
tail -f /var/log/nginx/access.log
Затем:
curl -Iv https://example.com/test-url
Если у virtual host свои журналы, смотреть нужно именно их. Пути зависят от серверной конфигурации.
Через systemd:
journalctl -u nginx
Для Apache:
journalctl -u apache2
journalctl -u httpd
Как читать результат, а не просто смотреть лог
| Что видно | Что это говорит о запросе | Куда идти дальше |
|---|---|---|
SSL_do_handshake() failed |
Ошибка возникла во время TLS до нормального HTTP-запроса | TLS-конфигурация, клиент, SNI, сертификат |
connect() failed (...) while connecting to upstream |
Nginx уже принял запрос, но не подключился к backend | PHP-FPM, socket, порт upstream |
upstream timed out |
HTTPS принят, backend отвечает слишком долго или не отвечает | PHP-FPM, приложение, база, upstream |
no live upstreams |
Прокси не имеет доступного backend | Конфигурация upstream и состояние сервисов |
В access.log появился 301 |
TCP и TLS уже пройдены, HTTP-запрос обработан | Смотреть Location и правила redirect |
В access.log появился 502 |
Веб-сервер принял HTTPS, но приложение/backend не отработал | PHP-FPM и upstream logs |
| В нужном access.log нет записи | Запрос не дошёл до этого virtual host или оборвался раньше HTTP | Другой vhost, TLS, proxy, DNS или сеть |
Например, браузер показывает 502 после перехода на HTTPS. Если access.log содержит запрос, а error.log — connect() failed while connecting to upstream, сертификат уже можно исключить. Nginx принял защищённое соединение, а проблема находится между ним и PHP-FPM.
Если запрос вообще не появляется в access.log
Отсутствие записи — тоже результат. TLS handshake мог оборваться до формирования HTTP-запроса, запрос мог попасть в соседний virtual host, Cloudflare мог не достучаться до origin или DNS ведёт не туда.
Можно временно одновременно смотреть глобальный error log и журнал нужного сайта, затем отправить один запрос через curl. Если он появился в другом vhost, проблема в выборе конфигурации. Если его не видит даже веб-сервер, возвращайтесь ниже — к proxy, сети и DNS.
Запрос появился в access.log — значит, сеть и TLS уже позади. Запроса нет — не нужно начинать с WordPress.
Как проверить HTTPS после исправления и не оставить скрытую проблему
Сайт открылся в браузере — это ещё не конец проверки после миграции. Можно починить основной домен по IPv4 и одновременно оставить сломанными www, IPv6, цепочку сертификатов или отдельные страницы WordPress.
Начните с базовых запросов:
curl -I http://example.com/
curl -Iv https://example.com/
curl -IL http://example.com/
Проверьте IPv4 и IPv6 отдельно, если опубликована AAAA:
curl -4Iv https://example.com/
curl -6Iv https://example.com/
Затем сертификат:
openssl s_client -connect example.com:443 -servername example.com </dev/null
Отдельно повторите проверку для www.example.com, если имя используется. Ситуация «apex работает, www показывает ошибку сертификата» после переноса вполне реальна: DNS, SAN или HTTPS virtual host для этих имён могут отличаться.
Для WordPress проверьте не только главную:
- несколько внутренних страниц;
/wp-admin/;- авторизацию;
- CSS и JavaScript;
- изображения;
- DevTools Console;
- mixed content;
- формы и API-запросы, если они используются.
При Cloudflare сравните обычный запрос и origin. Если прямой доступ к origin закрыт firewall для сторонних IP, учитывайте это при интерпретации теста.
Нужна не просто зелёная иконка в одной вкладке браузера, а предсказуемая работа всех реально используемых имён и сетевых путей.
В каком порядке диагностировать HTTPS, чтобы не менять настройки наугад
Самый быстрый маршрут после переноса — идти от нижних уровней к верхним. Нашли первую неисправность, исправили её, повторили тест. Не меняйте одновременно DNS, Nginx, Cloudflare и WordPress: после этого трудно понять, что именно было причиной.
- Проверьте DNS. A, AAAA,
www, основной домен и фактический IP. - Разделите IPv4 и IPv6. Выполните
curl -4иcurl -6, если IPv6 используется. - Проверьте TCP/443 снаружи. Используйте
ncилиcurl -Iv. - Посмотрите, кто слушает 443.
ss -lntpдолжен показать ожидаемый процесс. - Проверьте firewall. Включая security group или внешний сетевой фильтр.
- Проверьте Nginx или Apache. Syntax test и фактический HTTPS virtual host.
- Проверьте SNI. Нужный домен должен попадать в нужный vhost.
- Проверьте фактически выдаваемый сертификат. SAN, срок, issuer.
- Проверьте certificate chain. Для OpenSSL хороший ориентир —
Verify return code: 0 (ok). - Если есть Cloudflare или proxy, разделите edge и origin.
- Проверьте редиректы. Используйте
curl -ILи анализируйте каждыйLocation. - Только после этого переходите к WordPress.
home,siteurl, proxy headers, mixed content. - Повторите один запрос при открытых логах. Это покажет, до какого слоя запрос реально дошёл.
- После исправления проверьте все используемые имена и пути. IPv4, IPv6,
www, apex, внутренние страницы и origin при наличии CDN.
Для первого прохода часто достаточно:
dig +short example.com A
dig +short example.com AAAA
curl -4Iv https://example.com/
curl -6Iv https://example.com/
ss -lntp | grep ':443'
openssl s_client -connect example.com:443 -servername example.com </dev/null
Неправильный IP — исправляем DNS. На 443 никто не слушает — разбираемся с сервисом и firewall. TLS проходит, но сертификат чужой — проверяем SNI и virtual host. Сертификат нормальный, а в access.log появляется 301 или 502 — ниже уже не копаем, проблема находится на HTTP-уровне или в приложении.
В этом и состоит рабочая диагностика HTTPS после переноса: не угадывать причину по сообщению браузера, а последовательно доказать, какой уровень работает и на каком появляется первая ошибка.


