Сегодня в HomeLab появился ещё один самостоятельный узел. Я вынес
DeepSeek Harness в отдельную виртуальную машину, поднял его как обычный
Linux-сервис и подключил сразу к двум AI-провайдерам.
До этого Harness оставался скорее экспериментом: запустить процесс,
держать терминал открытым, при необходимости прокинуть SSH-туннель с Mac.
Для первых проб нормально. Для постоянного инструмента — уже нет.

Что хотелось получить
Требования были довольно приземлёнными:
- отдельная Ubuntu VM без смешивания с другими сервисами;
- автозапуск и восстановление процесса через
systemd; - web-интерфейс, доступный только из доверенной сети;
- локальная модель через собственный FreeDeepSeekAPI;
- OpenAI как второй провайдер через отдельный proxy-маршрут;
- никаких постоянных SSH-туннелей с рабочего Mac.
Публичные IP-адреса, ключи и точные параметры внутренней сети в статье
намеренно не привожу. На схеме остаются только роли узлов.
Как устроили узел
На новой VM установил Ubuntu и Node.js 24. Сам Harness запускается не из
ручной shell-сессии, а как unit systemd. Это небольшое изменение, но
именно после него эксперимент становится сервисом: процесс стартует после
перезагрузки, имеет понятный статус и пишет логи в journalctl.
Упрощённо unit выглядит так:
[Service]
Type=simple
User=harness
WorkingDirectory=/opt/deepseek-harness
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
EnvironmentFile=/etc/deepseek-harness.env
Это не копия production-файла, а безопасный пример структуры. Секреты и
адреса провайдеров лежат отдельно в environment-файле и не попадают в unit
или Git.
Перед приложением стоит nginx. Он принимает обращения из локальной сети и
передаёт их на loopback-порт Harness. Сам порт приложения наружу не
публикуется.
location / {
proxy_pass http://127.0.0.1:<HARNESS_PORT>;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
В итоге браузер больше не зависит от SSH-сессии на Mac. Открыл внутренний
адрес — получил тот же интерфейс.
Два провайдера, два маршрута
Первый backend — собственный FreeDeepSeekAPI в той же локальной сети. Это
короткий маршрут: Harness обращается к соседнему сервису напрямую, без
выхода наружу.
Второй — OpenAI. Для него настроен отдельный выход через proxy, потому что
прямое соединение из текущего региона не работает. Такой вариант мне
нравится больше глобального проксирования всей VM: наружу через proxy идёт
только тот трафик, которому это действительно нужно.
+--> local-ai-api
| прямой LAN-маршрут
browser --> nginx --> Harness
|
+--> proxy --> cloud AI
внешний маршрут
На бумаге всё просто. На практике именно здесь мы потеряли больше всего
времени.
Почему локальный API внезапно пошёл через proxy
После подключения провайдеров FreeDeepSeekAPI отвечать не захотел. Сначала
подозрение упало на сам API: порт, авторизация, формат запроса. Но сервис
был жив и с соседнего узла открывался.
Проблема оказалась в маршруте. Harness отправлял внутренний HTTP-запрос
через внешний proxy, хотя оба сервера находились в одном сегменте.
В NO_PROXY уже была указана локальная подсеть в CIDR-формате. Я ожидал,
что этого достаточно. Но используемая Node.js-цепочка обработки proxy не
сопоставила адрес так, как я рассчитывал. Универсального поведения здесь
нет: итог зависит не только от Node.js, но и от HTTP-клиента или
proxy-библиотеки приложения.
Исправление оказалось коротким — добавил в NO_PROXY точный адрес
локального AI-сервиса:
HTTP_PROXY=http://<PROXY_HOST>:<PROXY_PORT>
HTTPS_PROXY=http://<PROXY_HOST>:<PROXY_PORT>
NO_PROXY=localhost,127.0.0.1,<LOCAL_AI_IP>
После изменения перезапустил unit и посмотрел новый запуск:
sudo systemctl daemon-reload
sudo systemctl restart deepseek-harness
sudo systemctl status deepseek-harness
journalctl -u deepseek-harness -n 100 --no-pager
Локальный запрос сразу перестал уходить во внешний контур. Это тот случай,
когда одна запись в environment-файле чинит систему, но только после того,
как проверен реальный путь пакета.
Как проверяли
Я не стал считать успешную загрузку web-интерфейса финальным тестом. Она
подтверждает работу nginx и самого приложения, но ничего не говорит о
провайдере модели.
Финальная проверка прошла по всей цепочке:
клиент
-> nginx
-> DeepSeek Harness
-> FreeDeepSeekAPI
-> deepseek-chat
-> полноценный ответ
deepseek-chat вернул ответ примерно за семь секунд. Повторных попыток и
транспортных ошибок в журнале не было. Это важнее красивого статуса
active (running): сервис выполнил именно ту работу, ради которой его
разворачивали.
Что получилось
Теперь Harness — отдельный AI-инструмент внутри HomeLab, а не процесс в
случайном терминале:
- выделенная Ubuntu VM;
- Node.js 24;
- управление через
systemd; - локальный web-доступ через nginx;
- FreeDeepSeekAPI для внутренних запросов;
- OpenAI через отдельный proxy-маршрут;
- предсказуемое исключение локального API из проксирования.
Главный урок сегодня не про AI. Если приложение одновременно работает с
локальными и внешними API, переменная NO_PROXY требует такого же теста,
как firewall или таблица маршрутизации. CIDR может выглядеть правильно и
всё равно не сработать в конкретной библиотеке. Точный host/IP скучнее,
зато его поведение мы проверили.