Веб-сайт не работает, но сервер доступен? Отследите сбой от DNS к приложению
«SSH работает, сайт не работает» — начните с правильного вопроса
Начинают срабатывать оповещения, пользователи говорят, что сайт недоступен, и ваш первый тест дает вам странное облегчение: SSH все еще позволяет вам войти. Этот момент кажется обнадеживающим, потому что сервер не исчез. Но это также то место, где начинается много плохого устранения неполадок, потому что «я все еще могу войти» — это не то же самое, что «веб-сайт должен работать».

Полезный вопрос — это не «что я могу перезагрузить в первую очередь?» Это «какой уровень вышел из строя первым?» Рабочий сеанс SSH доказывает, что машина доступна на порту 22. Это не доказывает, что домен разрешается правильно. Это не доказывает:
- доступны ли порты 80 и 443
- здоров ли HTTPS
- отвечает ли приложение за веб-сервером
Это руководство построено на основе этого различия и сосредоточено на диагностике, а не на попытке стать полным руководством по nginx, DNS, TLS, Docker или базам данных.
⚠️ Предупреждение: Слепая перезагрузка nginx, Docker, PHP-FPM или всего VPS в первые минуты инцидента может стереть улики, которые вам нужны. Сначала соберите один раунд доказательств, затем измените только уровень, который действительно вышел из строя.
Карта сортировки за одну минуту

Прежде чем углубляться, ориентируйтесь. Форма сбоя часто подсказывает, какой уровень заслуживает внимания в первую очередь, даже если вы еще не знаете первопричину.
Рассматривайте следующую таблицу как ярлык сортировки, а не окончательный вердикт.
| Что вы видите | Что это обычно означает | Что проверить в первую очередь | Что не следует предполагать |
|---|---|---|---|
| 🧭 Could not resolve host | Имя не разрешилось в адрес | DNS записи, путь резолвера, опечатки | Веб-сервер обязательно является проблемой |
| ⏱️ Timeout | Трафик заблокирован, неправильно маршрутизирован или зависает дальше в цепи | Внешний curl, путь брандмауэра, маршрутизация, доступность слушателя | Все таймауты означают одно и то же |
| 🚫 Connection refused | Хост доступен, но ничего полезного не принимает соединения там | ss -ltnp, состояние сервиса, адрес привязки | Весь сервер отключен |
| 🔐 Предупреждение TLS или сертификата | HTTPS достиг 443, но уровень идентификации или handshake не прошел | Выданный сертификат, совпадение имени хоста, цепь, состояние обновления | Приложение определенно мертво |
| ⚠️ 502 / 503 / 504 | Доступный фронтенд или сервис отказывает выше в цепи | Передача вверх по потоку, доступность сервиса, местоположение таймаута | Каждая ошибка 5xx означает одно и то же исправление |
| 🏠 Работает локально, но не снаружи | Стек может быть в порядке на сервере, но внешний путь сломан | Брандмауэр хоста, брандмауэр провайдера, путь CDN, маршрутизация | Локальный успех доказывает публичную доступность |
Важен первый сломанный этап. Если DNS не работает, более поздние уровни — это шум. Если 443 отвечает, но TLS не прошел, приложение — это не ваш первый вопрос. Ментальная модель ниже — это то, что делает эту последовательность логичной вместо случайной.
Почему SSH не доказывает, что веб-сайт работает
SSH и веб-трафик — это разные пути с разными задачами. SSH на порту 22 доказывает, что вы можете достичь машины через её дверь удалённого управления. Веб-сайт зависит от портов 80 и 443, плюс слои позади них. Это отдельные тесты, поэтому “сервер доступен” и “веб-сайт доступен” — это не взаимозаменяемые утверждения.

Проще всего представить это как офисное здание. DNS помогает посетителю найти адрес здания. Порты 80 и 443 — это стойка регистрации для публичных посетителей. Веб-сервер — это администратор, который принимает запрос и решает, куда его направить. Приложение — это офис, который выполняет реальную работу. База данных или другая зависимость может находиться глубже в здании. SSH — это совсем другой вход. Он полезен для персонала, но не доказывает, что стойка регистрации открыта или что передача в офис работает.
Browser
↓
DNS lookup
↓
IP address
↓
Port 80 / 443
↓
Web server
↓
App / upstream
↓
Database / dependencyКогда люди говорят, что сервис “слушает”, они имеют в виду, что он фактически принимает соединения на ожидаемой конечной точке. Это различие превращает расплывчатый момент “сервер работает” в отслеживаемый путь запроса.
Это важно, потому что HTTPS может не работать до того, как приложение ответит, и сбои прокси или приложения могут произойти после того, как фронтенд уже доступен. Поэтому следующий шаг всегда одинаков: смотрите снаружи и найдите последний успешный этап запроса.
Шаг 1: Воспроизведите сбой снаружи сервера
Начните со стороны клиента, а не изнутри VPS. Если возможно, сначала протестируйте с другой сети или устройства, чтобы не спутать локальный DNS кеш, старую запись /etc/hosts или проблему локального брандмауэра/VPN с реальным сбоем сервера.
Используйте подробный внешний запрос, чтобы увидеть, как далеко запрос доходит перед тем, как упасть:
curl -v --connect-timeout 5 --max-time 15 https://example.com/curl -v здесь не инструмент только для экспертов. Читайте его как трассировку прогресса. Если он никогда не разрешает имя, вы находитесь в ветке DNS. Если он подключается и затем говорит Connection refused, хост ответил, но ничего полезного не принимает трафик там. Если он зависает до истечения времени ожидания, думайте о фильтрации, маршрутизации или более глубоком зависании позже в пути запроса. Если вы получаете HTTP ответ, даже страницу ошибки, вы уже прошли мимо уровня соединения и перешли в более высокую ветку.
💡 Совет: Сравните IPv4 и IPv6 на ранней стадии. Забытая запись AAAA может сделать сбой непоследовательным, потому что некоторые клиенты предпочитают IPv6 в первую очередь, а другие нет.
Запустите один и тот же тест один раз для каждого семейства протоколов при использовании двойного стека:
curl -4 -v --connect-timeout 5 --max-time 15 https://example.com/
curl -6 -v --connect-timeout 5 --max-time 15 https://example.com/Если IPv4 работает и IPv6 не работает, или наоборот, вы уже сузили инцидент быстрее, чем перезагрузка сервиса когда-либо могла бы. Если сбой начинается с разрешения имени или выбора назначения, DNS — это следующая чистая ветка для проверки.
Шаг 2: Проверьте DNS и подтвердите правильный пункт назначения
Перед отладкой nginx убедитесь, что домен действительно отправляет посетителей на сервер, который вы считаете правильным. Это особенно важно после миграций, изменений IP, корректировок CDN или частичного редактирования записей.
Сначала проверьте публичные записи:
dig +short A example.com
dig +short AAAA example.comЭти две строки отвечают на очень практический вопрос: где интернет считает, что находится example.com прямо сейчас? Одна распространённая ошибка — SSH по IP достигает нового VPS, но домен всё ещё указывает на старый адрес. Другая — запись A была обновлена, но запись AAAA всё ещё указывает на устаревший адрес. В этом случае только часть вашего трафика не работает.
📝 Примечание: curl --resolve безопаснее, чем изменение публичного DNS во время инцидента. Это позволяет вам протестировать источник, который вы намеревались использовать, сохраняя при этом имя хоста и SNI.
Используйте curl --resolve для принудительного теста против IP, который вы ожидаете, без изменения публичных записей:
curl --resolve example.com:443:203.0.113.10 https://example.com/Если это работает, а публичный домен всё ещё не работает, сервер может быть в порядке, а DNS может быть неработающим слоем. Одно замечание о ограниченном CDN стоит иметь в виду здесь. Если ваш источник заблокирован для приёма трафика только из диапазонов IP CDN, прямой тест источника может не пройти просто потому, что источник ожидает трафик от edge, а не произвольные публичные запросы. После подтверждения пункта назначения следующий вопрос — отвечает ли что-нибудь полезное на 80 или 443 там.
Шаг 3: Проверьте, что прослушивает порты 80/443
Теперь переключитесь на сервер и задайте узкий вопрос: действительно ли что-то принимает веб-соединения на ожидаемых портах? Машина может быть активна, SSH может работать, и nginx может быть даже установлен. Однако общедоступные веб-порты все еще могут не иметь полезного слушателя.
Сначала проверьте слушателей:
sudo ss -ltnpПустой вывод для :80 или :443 означает, что там ничего полезного не прослушивается. Слушатель на 127.0.0.1 означает, что сервис принимает соединения только с локальной машины. Слушатель на 0.0.0.0 означает, что он привязан к интерфейсам IPv4. [::] обычно означает интерфейсы IPv6. Не предполагайте, что привязка IPv6 автоматически гарантирует необходимый вам путь IPv4.
Затем используйте небольшой пакет проверки здоровья nginx перед любыми изменениями:
sudo systemctl status nginx --no-pager -l
sudo nginx -t
sudo journalctl -u nginx --since '-30 minutes' --no-pager- Если systemctl показывает active (running), это только доказывает, что процесс сервиса существует
- nginx -t показывает, является ли конфигурация действительной
- journalctl показывает, не произошла ли недавняя перезагрузка, не исчез ли файл сертификата или не сломался ли виртуальный хост при запуске.
Для читателей Apache эквивалентный синтаксис проверки — apachectl configtest. Как только вы узнаете, что что-то прослушивается, следующее доказательство более конкретно: отвечает ли правильный сайт локально, когда вы исключаете внешнюю сеть из уравнения?
💡 Совет: Сначала протестируйте конфигурацию, затем предпочитайте reload слепому перезапуску, если это уместно. Перезагрузка проверяет новую конфигурацию и сохраняет старых рабочих, если новая конфигурация неправильная; слепой перезапуск намного грубее посередине инцидента.
Step 4: Test the Site Locally with the Right Host and SNI
This is the most important fork in the whole investigation. A plain curl 127.0.0.1 can be misleading. Many servers host multiple sites and choose the response based on the Host header or, for HTTPS, SNI. You are not asking whether something responds locally. You are asking whether the correct site path responds locally.
Use local tests that preserve the hostname logic:
curl -I http://127.0.0.1/ -H 'Host: example.com'
curl -v --resolve example.com:443:127.0.0.1 https://example.com/
# Only as a one-off diagnostic if you already know the cert is bad:
curl -vk --resolve example.com:443:127.0.0.1 https://example.com/A meaningful success is the expected page, expected redirect, or expected application response from the correct site. It is not the default nginx host, the wrong certificate, or a generic “it returned HTML.” From here there are three clean outcomes: local success, local wrong-site or default-cert behavior, or local failure/timeout. A good local result points outward to firewall, provider, CDN, or routing checks. A bad local result keeps you inside the stack, in the upstream or TLS branches.
—
Шаг 4: Локальное тестирование сайта с правильным хостом и SNI
Это самое важное разветвление во всем расследовании. Простой curl 127.0.0.1 может быть обманчивым. Многие серверы размещают несколько сайтов и выбирают ответ на основе заголовка Host или, для HTTPS, SNI. Вы не спрашиваете, отвечает ли что-то локально. Вы спрашиваете, отвечает ли локально правильный путь сайта.
Используйте локальные тесты, которые сохраняют логику имени хоста:
curl -I http://127.0.0.1/ -H 'Host: example.com'
curl -v --resolve example.com:443:127.0.0.1 https://example.com/
# Only as a one-off diagnostic if you already know the cert is bad:
curl -vk --resolve example.com:443:127.0.0.1 https://example.com/Значимый успех — это ожидаемая страница, ожидаемое перенаправление или ожидаемый ответ приложения от правильного сайта. Это не хост nginx по умолчанию, не неправильный сертификат и не общий “он вернул HTML”. Отсюда есть три четких результата: локальный успех, локальное поведение неправильного сайта или сертификата по умолчанию, или локальный отказ/тайм-аут. Хороший локальный результат указывает на внешние проблемы: брандмауэр, провайдер, CDN или маршрутизацию. Плохой локальный результат держит вас внутри стека, в ветвях upstream или TLS.
Шаг 5: Если работает локально, но не снаружи, проследите сетевой путь
Когда локальный тест прошел успешно, на время перестаньте сомневаться в nginx. Стек сайта, вероятно, работает на сервере, и недостающий элемент обычно находится где-то между посетителем и этим рабочим локальным сервисом. Начните с брандмауэра хоста, так как это ближайшая внешняя граница, которой вы управляете.
Проверьте правила на стороне хоста с помощью инструмента, который фактически использует ваша система, и выполните одну быструю проверку здравомыслия на предмет самостоятельного блокирования:
sudo nft list ruleset
# Or, on systems still using iptables directly:
sudo iptables-save
sudo ip6tables-save
# Fast sanity check for self-inflicted blocking:
sudo fail2ban-client statusЭтот вывод показывает только уровень гостевой ОС. Он не показывает фильтрацию на стороне провайдера, группы безопасности или правила брандмауэра на уровне панели, которые находятся вне самого VPS. На VPS AlexHost, например, брандмауэр машины и любые сетевые элементы управления на уровне панели — это отдельные вопросы. Оба имеют значение, когда локальные тесты работают, но публичные посетители по-прежнему не могут получить доступ.
⚠️ Предупреждение: Если Docker публикует порты на хосте, не предполагайте, что вывод UFW рассказывает всю историю. Docker может маршрутизировать опубликованный трафик контейнера через NAT до обычных цепочек UFW. Это означает, что «UFW выглядит нормально» не всегда означает, что путь пакета в порядке.
CDN и балансировщики нагрузки также заслуживают отдельного рассмотрения. Источник может быть здоров и все еще недоступен напрямую, потому что только диапазоны IP граничных узлов могут с ним взаимодействовать. Когда вам нужно доказательство того, прибывают ли пакеты вообще, используйте tcpdump как инструмент да-или-нет:
📝 Примечание: Неудачный прямой тест источника за списком разрешений CDN обычно указывает на политику граничного узла, а не на мертвый источник. В такой конфигурации источник предназначен для доверия пути CDN, а не каждому прямому посетителю.
sudo tcpdump -ni any 'tcp port 80 or tcp port 443'Если вы вообще не видите пакеты SYN, трафик не достигает сервера. Если SYN-пакеты прибывают и SYN-ACK не уходит, сервер или путь брандмауэра все еще блокирует передачу. Если ни один из этих паттернов не кажется блокирующим, оставшиеся сбои обычно находятся за фронтенд-сервером в передаче вверх по потоку.
Шаг 6: Если фронтенд отвечает, но сайт всё ещё сломан, следуйте по цепочке upstream
В этом случае веб-сервер доступен, но следующий сервис за ним недостаточно здоров для завершения запроса. Здесь “upstream” означает сервис, к которому nginx передаёт запрос дальше: процесс приложения, runtime на основе сокета, контейнер или другую внутреннюю зависимость.
Статические страницы работают, а вход, поиск, оформление покупки или API маршруты не работают — это сильный признак того, что фронтенд присутствует и сбой начинается на этапе передачи за ним.
📝 Примечание: Рассматривайте 502 как “следующий сервис ответил неправильно” и 504 как “следующий сервис ответил слишком медленно”. Оба являются признаками того, что нужно следовать по пути upstream, а не останавливаться на фронтенде.
Проверьте активную передачу, затем протестируйте upstream напрямую:
sudo nginx -T
# Direct HTTP upstream example
curl -i http://127.0.0.1:3000/
# Unix-socket-backed HTTP example
curl --unix-socket /run/app.sock http://localhost/В выводе nginx ищите директивы такие как proxy_pass, fastcgi_pass или uwsgi_pass. Вы проверяете, указывает ли nginx на правильную цель, по правильному протоколу, на правильный порт или сокет. Если задействованы контейнеры, добавьте краткую проверку здоровья контейнера вместо угадывания:
docker ps
docker logs --tail 50 <container_name>
docker inspect --format '{{json .State.Health}}' <container_name>
docker port <container_name>Если прямой тест приложения не пройден, проблема находится за веб-сервером. Если он работает напрямую, но не работает через nginx, конфигурация передачи — это ветка для проверки. Доступность базы данных имеет значение только как проверка зависимости здесь, а не как отдельное глубокое погружение. Если этот паттерн сбоя upstream повторяется, это правильный момент для переключения на специализированное руководство по устранению неполадок вместо того, чтобы растягивать один инцидент на предположения.
Step 7: Isolate TLS and Certificate Failures
This branch is narrower: something is answering on 443, but the browser still cannot complete a clean, trustworthy HTTPS session. A successful TCP connection to port 443 does not prove the certificate, hostname match, or handshake path is healthy.
Inspect what certificate is actually being served:
openssl s_client -connect example.com:443 -servername example.com -verify_hostname example.com -briefThis is where you catch the common failure shapes: the wrong hostname, an expired certificate, an incomplete chain, or a renewal that never finished cleanly. In plain language, SNI tells the server which hostname you meant. -verify_hostname checks whether the certificate it served matches that hostname. After recovery, validate the renewal path so this does not become the next outage:
⚠️ Warning: If you rely on HTTP-01 validation for certificate renewal, inbound port 80 must be reachable. A firewall or provider rule blocking 80 can quietly break renewals long before users report that HTTPS looks dead.
sudo certbot renew --dry-runШаг 8: Проверьте нагрузку на ресурсы перед тем, как считать это случайным
Некоторые инциденты вообще не являются сбоями доступности. Маршрут технически целостен, но сервер слишком истощен, заблокирован или перегружен, чтобы ответить вовремя. Вот когда сайт может выглядеть “частично живым” с одной стороны и все еще казаться мертвым для пользователей.
Запустите небольшой первоначальный пакет ресурсов:
df -h
df -i
free -h
uptime
vmstat 1 5
sudo journalctl -k -g 'oom|out of memory|killed process'Читайте результаты в паттернах, а не изолированно.
- df -h показывает обычное исчерпание диска.
- df -i ловит исчерпание inode, когда место кажется существующим, но файловая система не может создать больше записей.
- free -h имеет значение в основном, когда доступная память коллапсирует и активность swap возрастает.
- uptime может показывать высокую нагрузку даже когда CPU не перегружен, что часто означает, что задачи ждут давления на диск или память, а не активные вычисления.
- Строки журнала ядра об событиях OOM говорят вам, начала ли система убивать процессы, чтобы выжить.
Графики провайдера могут подтвердить временную шкалу. На VPS AlexHost они могут быть полезны для проверки того, совпадают ли скачки в RAM, диске или I/O с отключением. Но доказательства терминала должны по-прежнему вести диагностику. Этот раздел не является руководством по настройке; это ветвь, которая говорит вам, что сайт может быть неудачным под давлением, а не неудачным в маршрутизации.
Думайте слоями, а не паникой

Когда SSH работает, но сайт не открывается, держите цепь короткой и повторяемой:
- воспроизведите сбой снаружи
- определите последний успешный этап
- подтвердите DNS и назначение
- проверьте наличие реального слушателя на 80/443
- протестируйте правильный сайт локально
- разветвитесь на сетевой путь, upstream, TLS или ресурсы
💡 Совет: Не закрывайте последний рабочий сеанс SSH, пока не подтвердите, что свежий вход все еще работает и у вас все еще есть резервный путь доступа, например доступ через консоль провайдера. Во время активного инцидента сохранение контроля так же важно, как исправление первого симптома.
Держите привычки легкими: мониторьте снаружи, ведите логи и тестируйте сертификаты с помощью certbot renew –dry-run. Защитите доступ резервными копиями и путем консоли. Инструменты провайдера — брандмауэр, графики, консоль (включая AlexHost) — должны поддерживать устранение неполадок, а не заменять его. Сосредоточьтесь на исправлении первого сломанного слоя, чтобы каждый инцидент обрабатывался с более четкими доказательствами и меньше паники.
на всех хостинговых услугах