Проверка доступности сайта из разных стран после переезда на Hetzner Helsinki
Полтора месяца назад я начал переезд всей инфраструктуры с латвийского VPS на Hetzner в Хельсинки: 22 продакшен-приложения, 5 публичных API, мониторинг, бэкапы и пачка Telegram-ботов уехали в Финляндию. Сегодня финальный шаг - пройтись по чеклисту независимого аудита, убедиться что всё переехало нормально, и нажать кнопку «выключить старый сервер навсегда». А заодно мне нужна честная проверка доступности сайта из разных стран и регионов РФ: как мой реальный Next.js рендерится из Москвы, Питера, Новосиба и других городов после переезда в Хельсинки. Спойлер: старый сервер уже мёртв, всё работает, тесты пройдены. Но интересные сюрпризы по дороге всё-таки случились.
Зачем вообще переезжать
Латвийский провайдер был неплох: дешёвый, стабильный, без сюрпризов. Но за полгода эксплуатации накопились три причины, которые в сумме перевесили любую инерцию. Во-первых, ресурсов перестало хватать — 5.8 GB RAM, из которых 3.9 GB постоянно занято, плюс 1.4 GB активного свопа. Twenty CRM, Supabase, parser-hub, lobechat и десяток мелких сервисов делили память так плотно, что любой пик трафика превращался в OOM-killer-лотерею. Во-вторых, я хотел консолидации: все мои pet-проекты разбросаны по трём провайдерам, бэкапы делаются вручную, секреты хранятся в трёх разных .env-папках. В-третьих, Hetzner предлагал dedicated-сервер EX44 с Ryzen 9 3900 (12 cores), 128 GB ECC RAM и 2×1.92 TB NVMe RAID-1 за цену чуть выше моего латвийского VPS. Это в десять раз больше памяти и в двадцать раз больше диска.
Переезд я делал постепенно, app-by-app, через Dokploy — self-hosted PaaS на замену Vercel, который с июня 2025 заблокирован в России. Архитектура получилась двухслойной: Caddy на хосте обрабатывает 80/443 и SSL для всех доменов, проксирует по Host-header в Dokploy Traefik на внутреннем порту, а тот уже раздаёт трафик в Docker Swarm services. CI/CD собран на GitHub Actions + GHCR (Container Registry), с финальным шагом через SSH — потому что родной application.deploy Dokploy не делает force-pull для тега :latest и Swarm переиспользует закэшированный образ.
Чеклист аудита: 10 пунктов
Переезд я делал сам, поэтому финальный аудит решил пройти как независимый проверяющий — со свежей головой и без оптимизма автора. Чеклист родился органически: я выписал всё, что могло бы сломаться при отключении старого сервера, и пошёл по списку.
1. DNS. 11 публичных доменов. Десять должны указывать на Hetzner, один — all.pashavin.ru — намеренно остаётся на старом фронте по другому маршруту. Всё совпало.
2. HTTPS. Прохожу curl -Is по всем доменам, ожидаю 200/307/401/404 — нормальные ответы. Никаких 5xx, таймаутов или ошибок SSL. Все 11 доменов отвечают корректно.
3. System services. На Hetzner крутится 17 systemd-сервисов: anti-api, crm-messenger, follower-check (с туннелем), пара рендереров, headless-API и прочее. Все в статусе active.
4. User services. После переезда обнаружил приятный сюрприз: дубликат kp-renderer в user-режиме (~/.config/systemd/user/), который тихо конкурировал с system-версией. Удалил, обновил документацию миграции.
5. Docker. 24 контейнера в running, ноль в restarting.
6. Gatus. Self-hosted мониторинг от TwiN. Расширил конфиг до 12 endpoints: добавил группу monitoring (mon-api, beszel, gatus self-check, logs), все 12 проверок зелёные на первом тике.
7. Telegram-боты. Проверил логи на 409-conflict ошибки за последние 30 минут — это типичный симптом, когда два инстанса бота конкурируют за long-poll. Ноль конфликтов значит, что старый сервер уже никого не забирает.
8. RAID. mdadm --detail показывает три зеркала в состоянии [UU] — оба диска живые.
9. Disk. 116 GB занято из 1.8 TB — 7%. Запас на годы вперёд.
10. WireGuard. Туннели до парсер-хабов и follower-check сервиса работают, пинг проходит.
Когда я нажал «отключить» на латвийском VPS, ping сразу показал 100% packet loss. Сервер мёртв. Всё, что должно было переехать — переехало.
Тесты доступности из России
Переезд в Финляндию — это всегда вопрос: как мой сайт работает из России? Hetzner Helsinki географически ближе к Москве, чем условный Frankfurt, но политически — это тот же EU. Я хотел получить реальную карту: с каких провайдеров и регионов сайт грузится быстро, где может быть деградация, где timeout. Идеально — без бюджета.
Pipeline A: Globalping
Первая находка — Globalping от jsDelivr. Open-source, REST API, 100 RU-проб в семи городах: Москва, Питер, Новосибирск, Таганрог, Краснодар, Казань, Уфа. Free-тариф — 250 тестов в час без регистрации. Поддерживает HTTP/ping/traceroute/DNS, выдаёт TTFB и status code. Главный минус — это не браузерный тест, чисто HTTP-уровень. Но для проверки «дойдёт ли пакет и за сколько» этого достаточно.
API элементарный: POST с описанием measurement (target, type, locations), затем polling до получения результатов. Один нюанс — anonymous tier ограничен 50 пробами на запрос, не 100, как написано в документации. Узнал я это, разумеется, методом 400 Bad Request.
Pipeline B: Playwright + free proxies
Для браузерного теста — Playwright Chromium headless через бесплатные RU-прокси из public-листов. Идея: для каждого живого прокси открыть https://test.pashavin.ru/, замерить FCP, LCP, DOM Content Loaded, console errors. Реалистично-выглядящая картина того, как пользователь у Билайна или МТС видит сайт.
Реальность ударила в лицо: 16 alive HTTP-прокси из листа, и ни один не поддерживает CONNECT-метод для HTTPS. Все дают ERR_EMPTY_RESPONSE на TLS-handshake. Это нормально для бесплатных публичных прокси — они расчитаны на скрапинг плоского HTTP, а не на туннелирование зашифрованного трафика. Результат через прокси оказался нерепрезентативным, но это сам по себе data point: free RU-proxies для production-класса HTTPS-тестов не годятся, нужны residential-прокси или платные API.
Тестовая площадка: test.pashavin.ru
Чтобы прогон был честным, я развернул на Hetzner реальный Next.js — feberra-landing-page, статичный лендинг, который умеет рендерить SSR. Pull образа с KZ-сервера через SSH-pipe (227 MB), запуск через docker run на внутреннем порту, добавление Caddy-блока:
test.pashavin.ru {
reverse_proxy 127.0.0.1:3099
header Server-Timing "app;desc=feberra-test"
}
SSL Caddy получил автоматически через Let's Encrypt. Локально — 200 OK на 31 мс. Перехожу к замерам.
Результаты прогона
Globalping выдал 49 успешных проверок из 50 (одна Penza с ER-Telecom/Dom.ru ушла в timeout). Распределение по городам:
| Город | OK | Avg TTFB |
|---|---|---|
| Москва | 27/27 | 36 ms |
| Санкт-Петербург | 11/11 | 21 ms |
| Новосибирск | 5/5 | 97 ms |
| Казань | 2/2 | 55 ms |
| Краснодар | 2/2 | 48 ms |
| Уфа | 1/1 | 39 ms |
| Таганрог | 1/1 | 56 ms |
| Пенза | 0/1 | timeout |
21 мс TTFB из Питера до Хельсинки — это лучше, чем многие сайты у крупных VPS внутри России. 36 мс из Москвы — на уровне локальной сети. p95 latency по всем 49 пробам — 178 мс.
Playwright локально (Hetzner→Hetzner) показал TTFB 46 мс, FCP 200 мс, networkidle 877 мс, ноль console errors, ноль failed requests. Реальный Next.js, реальный SSL, реальная отдача.
Дополнительно я прогнал check-host.net на тот же URL — 3/3 RU-нод OK (Moscow 208 мс, СПб 96 мс, Ekb 242 мс), ping из Питера 9 мс. Все три независимых инструмента сходятся: сайт из России грузится корректно и быстро.
Один сюрприз: Penza timeout
Единственный фейл — нода в Пензе на ER-Telecom/Dom.ru. Это не блокировка, скорее routing issue или peering-проблема между конкретным региональным ISP и Hetzner. Воспроизвести стабильно я не смог: повторные прогоны показывали то OK, то timeout. Решил не паниковать — 1 из 50 в одном городе при первом замере это статистический шум, а не системная деградация.
Зато из этого получилось понимание: если хочется ловить такие региональные блипы заранее, нужно ставить периодический мониторинг через тот же Globalping API в Gatus, а не разовый прогон. Положил в backlog.
Что я понял про переезды
Главный урок этого переезда — аудит важнее самой миграции. Сам процесс переезда занял три недели вечеров, по 2-3 часа за раз. А вот финальный чеклист, который я прошёл за час, поймал реальный артефакт (дубликат kp-renderer как user-unit), который тихо ел ресурсы и при отключении KZ мог бы внезапно остановить рендер. Без аудита я бы выключил Латвию и удивлялся через сутки, почему один из сервисов лежит. Чеклист на десять пунктов — это копеечная страховка против фейла на 1 AM в субботу.
Второй урок — тестировать инфраструктуру с позиции пользователя, а не сервера. На Hetzner всё работает, в логах всё зелёно, healthcheck из самого Hetzner отдаёт 200. Но пока я не прогнал реальные RU-ноды через Globalping, я не знал, как сайт выглядит с точки зрения москвича на Билайне. Оказалось — отлично. Но мог бы оказаться и плохо: если бы Hetzner попал в чей-то блок-лист или peering-таблицу одного из крупных RU-ISP. Проверка из инфраструктуры РФ — это не paranoia, это базовая гигиена для любого проекта с русскоязычной аудиторией.
Третий урок — бесплатные инструменты решают 80% задач. Globalping покрыл breadth-тест по RU-провайдерам полностью бесплатно. Playwright + free-proxy сценарий не сработал из-за HTTPS, но это сам по себе полезный вывод: для глубоких браузерных тестов из реальных RU-ISP бесплатных опций нет, и это надо учитывать в планировании. Если бы я начинал с расчётом «куплю Bright Data за $30», я бы не открыл для себя Globalping — а это инструмент, который я теперь буду использовать на каждом deploy.
Четвёртый урок про инфраструктурный консолидейшн. До переезда у меня было три VPS у трёх провайдеров, бэкапы вручную, секреты в трёх местах, мониторинг частичный. После переезда — один dedicated на Hetzner, один резервный на KZ для legacy, единый Caddy с SSL для всех 22 доменов, daily-бэкапы с retention 7 дней в /opt/backups, Gatus отслеживает 12 endpoints, Beszel показывает живые метрики. Это не просто экономия денег (хотя и это тоже): это снижение когнитивной нагрузки. Я больше не помню три набора credentials, не путаю, на каком сервере крутится какой проект, не дрожу за бэкапы. Один сервер, который можно держать в голове целиком, — это огромный психологический апгрейд.
Пятый урок — никогда не недооценивай «дубликаты и забытые юниты». После любой миграции всегда останутся артефакты: старая конфигурация, второй systemd-юнит, забытый cron, висящий в /etc/cron.d, докер-контейнер, который ты ручную запустил месяц назад и не убил. Финальный аудит — это шанс их выловить, пока миграционный контекст ещё в голове. Через месяц ты уже не вспомнишь, зачем было два рендерера.
Латвийский сервер мёртв. Hetzner живёт, мониторится, бэкапится и отвечает из России за 21-36 миллисекунд. Это успешное завершение переезда — и неплохой задел на следующий цикл оптимизаций.

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.