Logo Craft Homelab Docs Нейросети Контакты Telegram
Домашняя AI-платформа на двух нодах: сеть, отказоустойчивость, GPU Трендовые github проекты в нашем телеграм канале. Подпишись →
11 сентября 2026 г.

Как устроена AI-платформа, которая живёт на железе под столом

Запустить чат-бота на одной модели можно за вечер. Превратить это в платформу с несколькими каналами доставки, биллингом, RAG и локальными моделями на GPU — задача другого масштаба, и решать её в облаке для соло-проекта часто просто невыгодно: постоянно работающий backend, очереди, две базы данных, объектное хранилище, векторная база и GPU-инстанс для инференса обходятся в десятки тысяч рублей в месяц ещё до первого пользователя. Домашнее железо — это разовые расходы и электричество. Ниже — архитектура, которая выдерживает такую нагрузку на двух нодах дома, и грабли, на которых она стоит.

Зачем платформе своя маршрутизация

Если платформа работает одновременно с провайдерами внутри страны и зарубежными AI-сервисами, у трафика появляются разные требования. Локальные API должны ходить напрямую — заворачивать их в туннель означает добавлять задержку и лишнюю точку отказа там, где её не было. Зарубежные провайдеры, наоборот, выигрывают от резервирования: один упавший канал не должен обрушивать чат-бота.

Рабочая схема для дома выглядит так:

  • домашний роутер (например, MikroTik) с двумя аплинками от провайдера;
  • трафик к локальным сервисам уходит напрямую через обычный ISP-канал;
  • трафик к зарубежным AI-провайдерам балансируется по нескольким туннелям до VPS через ECMP, причём часть туннелей терминируется прямо на сервере платформы — он сам становится одним из egress-узлов собственной сети;
  • список префиксов, которые считать “внешними”, не поддерживается руками: отдельный сервис на VPS собирает актуальные списки, генерирует конфиг для BIRD и раздаёт маршруты на роутер по BGP.

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

Отдельная категория проблем — автоматические обновления системы, которые незаметно меняют сетевые правила. Ночное обновление openssl может перезапустить systemd-networkd, а тот по умолчанию считает чужие правила policy routing своими и удаляет их (ManageForeignRoutingPolicyRules=yes). Внешне это выглядит как “сервис не отвечает”, хотя ip route ничего подозрительного не покажет — таблицы маршрутов остаются на месте, пропадают только правила, заворачивавшие конкретный трафик в туннель. Лечится одной строкой в drop-in конфиге (/etc/systemd/networkd.conf.d/*.conf, ManageForeignRoutingPolicyRules=no): всё, что настроено через ip rule вручную или собственными юнитами, должно либо явно жить внутри networkd, либо networkd должен быть отключён от управления этими правилами.

Микросервисы как деление по зонам отказа

Соло-разработчику держать несколько десятков контейнеров кажется избыточным, пока не сформулируешь задачу иначе: это деление по зонам отказа, и при падении одного компонента остальные должны продолжать работать.

Практическое деление выглядит так:

  • ядро платформы — монолитный backend (например, на FastAPI) с основной бизнес-логикой;
  • каждый канал доставки (Telegram, VK, Discord, веб-сокеты, интеграционный шлюз для внешних систем) — отдельный сервис: если один мессенджер лёг сам или упал его гейтвей, остальные каналы продолжают работать;
  • биллинг — отдельно, потому что это деньги и отдельная ответственность;
  • медиа и обработка файлов — отдельно, потому что это самая прожорливая и наименее стабильная часть системы;
  • воркеры очередей — отдельно, чтобы фоновая нагрузка не конкурировала с пользовательскими запросами;
  • вспомогательные сервисы (голосовой агент, веб-поиск, антивирус для загрузок) — каждый в своей изолированной единице.

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

Три урока про хранение данных

Первый: не держите Docker через snap-пакет в проде. Пути volumes, неожиданные обновления в произвольный момент и сюрпризы AppArmor рано или поздно выльются в аварийный вечер. Переезд на обычный apt-пакет стоит планировать заблаговременно, пока диск ещё не начал сыпать алертами.

Второй: при переезде на новый диск размер образов в реестре — плохой ориентир, docker save пишет несжатые слои, поэтому нужное место стоит оценивать по docker system df. Пины образов по digest (image@sha256:...) не переживают save/load и требуют повторного pull. И без restart: always контейнеры, остановленные руками перед клонированием диска, Docker не поднимет автоматически после ребута.

Третий: мажорный апгрейд PostgreSQL через pg_dumpall рискован, если часть контрактов приложения хранит физические OID ролей и баз — dump/restore их меняет и ломает эти контракты. Безопасный путь — pg_upgrade, и сначала на копии: у мажорных версий PostgreSQL есть свои тонкости с членством в ролях.

Отдельно — правило для сетевых томов: если stateful-сервис хранит данные на NFS, а том временно “подвис” (stale file handle), restart контейнера создаёт пустой каталог под протухшим маунтом и фактически переустанавливает сервис заново. Правильная последовательность — сначала stop, потом восстановление маунта, и только потом start.

Свой CI/CD и наблюдаемость — не излишество даже для одного человека

Собственный раннер CI (например, Gitea Actions) с отдельным registry избавляет от привязки к чужой инфраструктуре и даёт контроль над пайплайном: компилируемость → юнит-тесты по зонам → контрактные тесты на инварианты (биллинг, каналы доставки) → деплой-воркфлоу со сборкой образов, preflight-проверкой и rolling-обновлением без простоя.

Ключевая практика, которую легко пропустить на старте, — smoke-тесты сразу после деплоя по ключевым пользовательским сценариям. Без них о сломанной после выката авторизации первым узнаёт живой пользователь, а система мониторинга — задним числом.

Наблюдаемость для домашней инфраструктуры строится по тому же принципу, что и в любом дата-центре: метрики со всех нод, экспортёры на каждый значимый компонент (веб-сервер, базы данных, векторное хранилище, контейнеры через cAdvisor, GPU), алерты, приходящие сразу в мессенджер, и мониторинг состояния ИБП через NUT — просадка электричества для домашнего сервера такая же реальная угроза, как падение сервиса.

Полезно закладывать заранее и то, что на старте пет-проекта выглядит преждевременным: систему обратной связи с пользователями и базовую аналитику. Фидбек-петля должна существовать ещё до появления первого пользователя — выстраивать её в спешке после первой жалобы уже поздно.

GPU-нода: локальные модели рядом с основным сервером

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

Практические наблюдения по эксплуатации:

  • модели, которые должны быть быстро доступны, стоит держать резидентно в VRAM через отдельный sidecar-процесс, который периодически “пингует” их и не даёт runtime выгрузить модель после простоя — иначе первый запрос после паузы ждёт лишние секунды;
  • локальная модель распознавания речи может быть на порядок быстрее реального времени и разумно ставится первым провайдером в цепочке, а облачный STT — фолбэком;
  • MoE-архитектура экономит только вычисления: резидентный объём VRAM определяется полным размером модели независимо от числа активных параметров, поэтому небольшое число активных параметров легко вводит в заблуждение, и модель может вытеснить из памяти другие резидентные модели. Надёжнее проверять такие вещи на своих промптах и своей резидентности, чем ориентироваться на цифры из чужих бенчмарков;
  • если управление Docker на GPU-ноде идёт через переменные окружения, указывающие на демон основного сервера, docker ps без явного контекста на самой ноде покажет чужой прод — явное указание контекста в скрипте страхует от случайного пересоздания не того контейнера.

Что важно закладывать заранее

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