Один вечер, ноль даунтайма: как мы вернули сайт в Россию без VPN и чужих облаков
Разбор для тех, кто собирает продукт с ИИ-агентом и столкнулся с той же болью: сайт на зарубежном облаке, из России открывается через раз или только с VPN, а «переезд» пугает. Это репортаж о том, как платформа «Верный путь» за один вечер перевезла сайт на собственный VPS в Москве — с CI/CD и возможностью отката. Все шаги воспроизводимы: если вы vibe-кодите с агентом (Claude Code, Cursor, любой ИИ-помощник), сможете повторить за один сеанс.
Коротко
Кейс от 01.10.2026: сайт платформы «Верный путь» переезжал с зарубежного облака Vercel на VPS-сервер Timeweb в Москве — из-за SNI-фильтра (часть российских провайдеров не открывает зарубежные хостинги без VPN), неудобного биллинга и 152-ФЗ. Переезд занял один вечер и прошёл без простоя: пользователи не заметили ничего. Делали вдвоём с ИИ-агентом (Claude Code) — весь текст ниже воспроизводим.
Что получилось: обновление сайта осталось «одним git push» — CI/CD на GitHub Actions собирает standalone-сборку Next.js и выкладывает её на сервер в Docker-контейнер.
Сколько времени: перенос сайта — один вечер; скорость загрузки из РФ упала с «больше секунды, иногда не дожидался» до примерно 0,15–0,2 секунды.
Старый хостинг Vercel оставлен живым как резерв: откат — смена двух DNS-записей, минуты.
Как выглядела проблема
Сайт платформы жил на Vercel — стандартный выбор для Next.js: бесплатный (для учебных проектов), деплой из коробки, HTTPS сам. Но с точки зрения российской аудитории у этой схемы три вилки:
Доступ из РФ. Часть провайдеров режет путь до зарубежных облаков. Мы это уже проходили: прежний домен проекта перестал открываться из России из-за SNI-фильтра — и даже не начал индексироваться. Спасались связкой «Cloudflare-прокси из РФ», но путь удлинялся: на компе владельца сайт грузился больше секунды, а иногда и вовсе не дожидался первого байта.
Биллинг. У Vercel бесплатный тариф — для некоммерческого использования. А оплата Pro-тарифа ($20 в месяц) из России — отдельный квест с картой другого государства и посредниками.
152-ФЗ. Когда платформа становится рабочей и у неё появляются реальные пользователи из России, их персональные данные желательно хранить в РФ — а не в чужой юрисдикции.
У нас железо уже стояло: неделю назад на VPS-сервер Timeweb в Москве мы перевезли весь стек Supabase (базу данных, авторизацию, файловое хранилище, почту). Оставался последний кусок — сам сайт. И он был самым интересным: сайт нужно было не «положить и обновить руками по FTP», а перевезти вместе с нормальным деплой-пайплайном, чтобы обновление дальше оставалось «одним git push».
Решение в двух словах
Итоговая архитектура теперь выглядит так: собственный сервер в Москве (VPS) → Docker-контейнер с сайтом → обратный прокси caddy → DNS у Cloudflare (без проксирования, «серая тучка»). Рядом, на том же сервере, живёт весь остальной стек — и всё общается внутри одной закрытой сети контейнеров. Зарубежный сервис Vercel остаётся жив как резерв: если с сервером что-то случится, откат на облако — это смена двух DNS-записей, разлезается за пару минут.
Шаг за шагом (для повтора с ИИ-агентом)
1. Сборка: standalone
В настройках Next.js включается output: "standalone". Сборка тогда кладёт в итоговую папку не «весь мир node_modules», а сервер и самый необходимый минимум. У нас это было 37 мегабайт — и весь «деплой» помещается в один архив. На Vercel этот флаг вообще игнорируется — так что включать его безопасно даже если вы ещё не решили, куда переезжаете.
2. Поднимаем контейнер на своём сервере
Контейнер делается из официального образа node:22-alpine. Внутри — только команда node server.js, код приходит из примаунченного каталога с релизами. Секреты (ключи Supabase, SMTP) — файлом рядом, не в репозитории. Если у вас уже стоит docker-compose, это 10 минут.
3. CI/CD: GitHub Actions

Пайплайн оказался простым и бесплатным: репозиторий приватный, но бесплатной квоты GitHub Actions хватает с запасом:
npm ci— установка зависимостей;юнит-тесты — быстрые, без доступа к базе;
сборка standalone;
упаковка в архив и
scpна сервер;серверный скрипт: распаковать релиз в каталог с временной меткой, переключить симлинк, пересоздать контейнер, почистить старые релизы (хранятся последние 3 — то есть откат на предыдущую версию = одна команда).
Публикация новой версии сайта теперь — обычный git push. Никаких ручных FTP-заливок.
4. Прокатка на валидационном поддомене
Ключевая привычка, которая спасает от многих историй «упало после переезда»: до переключения боевого домена прокатать всё на отдельном поддомене. Мы подняли site.myrightway.ru, потыкали руками главную, каталог, логин, загрузку картинок — и лишь затем переключали боевой адрес.
5. Переключение DNS без простоя

Оба адреса — с www и без — переключили на новый сервер, TTL поставили 120 секунд. Сертификаты HTTPS сам выпустил caddy — он умеет автоматически заказывать Let's Encrypt. Старая версия не отключалась ни на секунду: DNS просто изменил адрес назначения, а кто-то с уже закэшированным старым адресом ещё несколько минут ходит на старое место, потом переезжает сам. Даунтайм — 0 секунд.
Наши грабли (чтобы вы них не наступили)
Честно о том, что не заработало с ходу — это самое полезное в любом таком разборе:
502 от прокси после подъёма контейнера. Контейнер «стоил», а сайт отдавал 502. Причина: в docker-compose внешнюю сеть нужно объявлять на уровне конкретного сервиса, а не только в глобальном разделе. Compose молча создал свою дефолтную сеть — и прокси не смог найти контейнер по имени. Вывод: после подъёма проверяйте не «контейнер жив», а «какая сеть реально применилась».
SSH-ключи известного хоста в Actions. Деплой из CI падал с «Host key verification failed» — и по логам сервера это выглядело как сетевая проблема. Реально: переменная окружения не подхватилась, известный хост надо передавать опцией команды ("-o UserKnownHostsFile=..."), а не через окружение.
CSP ломается от отсутствующего пробела. Один раз заголовок безопасности склеился без пробела между двумя значениями — браузер считал всё единым недопустимым токеном и тихо отбрасывал запросы, без единой ругани в консоли. Урок: заголовки проверять по факт-ответу продакшена (curl), а не только в коде.
DNS-кэш. После переключения часть пользователей ещё пару минут видит старую версию — это нормально (TTL). Заранее предупреждаем и не паникуем.
Зачем это менторам платформы

Для пользователей продукт изменился в главном: попасть на платформу теперь можно без VPN, с любого провайдера РФ — страницы грузятся в 6–7 раз быстрее по прямому пути (порядка 0,15–0,2 с против больше секунды через прокси). Дальше по плану — это же железо снизит зависимость от любых зарубежных лимитов и позволит спокойно добавлять функции, которым нужен длинный ответ сервера (видео, тяжёлые материалы, аналитика).
Что бы мы посоветовали тем, кто в похожей ситуации
Не жди «правильного момента»: полный переезд занял один вечер, включая прокатку поддоменом, отладку CI и переключение.
Включи standalone-сборку заранее — она ничего не ломает, а архив для деплоя получается крошечный.
Собери свой «плейбук отката»: снимок DNS-записей, старый хостинг держи живым хотя бы пару недель. Снять снимок — пять минут, спать спокойней.
Прокатывай на поддомене перед боевым переключением — там безопасно ловить «затёртые» заголовки и DNS-причуды.
Держи DNS TTL маленьким (120 сек) в период переезда: откат и вперед, и обратно, занимает минуты.
Не срезай юнит-тесты из CI ради скорости пайплайна — это твоя страховка от «я же ничего не менял» при переносе.
Итог

Сайт «Верного пути» теперь физически живёт в Москве: одна виртуалка, один контейнер, один прокси, один git push до новой версии. Проблема «из РФ только с VPN» закрыта на уровне архитектуры, а не очередного прокси-костыля. Если вы vibe-кодите с агентом, весь этот пайплайн — в пределах одного сеанса с ИИ-ассистентом: у нас получилось, у вас получится.
Вопросы, замечания, своя история переезда — напишите в комментариях или через форму у нас на сайте. И заходите в каталог менторов: там теперь открывается без VPN. 😉



