🐳 Docker Guide — OmniRoute (Русский)
Быстрый запуск
Заголовок раздела «Быстрый запуск»Самостоятельное размещение одной командой? См. руководство по самостоятельному размещению —
docker compose -f docker-compose.selfhost.yml up -d(опубликованный образ + Redis, доступ только через loopback-интерфейс, без выбора профиля). Приведённый ниже быстрый запуск — это вариант с одним контейнером для пользователей, у которых Redis уже запущен отдельно.
docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latestС файлом переменных окружения
Заголовок раздела «С файлом переменных окружения»# Сначала скопируйте и отредактируйте .envcp .env.example .env
docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ --env-file .env \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latestDocker Compose
Заголовок раздела «Docker Compose»# Базовый профиль (без инструментов CLI)docker compose --profile base up -d
# Профиль CLI (встроенные Claude Code, Codex, OpenClaw)docker compose --profile cli up -d
# Профиль хоста (в первую очередь для Linux; монтирует бинарные файлы CLI хоста в режиме только для чтения)docker compose --profile host up -d
# Веб-профиль (Chromium/Playwright для провайдеров веб-сессий)docker compose --profile web up -d
# Совместное использование CLI и вспомогательного контейнера CLIProxyAPIdocker compose --profile cli --profile cliproxyapi up -dДоступные профили
Заголовок раздела «Доступные профили»OmniRoute предоставляет профили Compose для основных вариантов развёртывания. Выберите профиль, соответствующий вашей среде.
| Профиль | Сервис | Когда использовать | Команда |
|---|---|---|---|
base (по умолчанию) |
omniroute-base |
Сервер без графического интерфейса / минимальная среда выполнения, CLI провайдеров не включены | docker compose --profile base up -d |
cli |
omniroute-cli |
Агентные рабочие процессы, вызывающие omniroute providers/setup/doctor и включённые CLI (Codex, Claude Code, Droid, OpenClaw) |
docker compose --profile cli up -d |
host |
omniroute-host |
Хосты Linux, которым нужен доступ к CLI хоста, аналогичный network_mode, путём монтирования ~/.local/bin, ~/.codex, ~/.claude и т. д. только для чтения |
docker compose --profile host up -d |
cliproxyapi |
cliproxyapi |
Запуск вспомогательного контейнера CLIProxyAPI на порту 8317 для проксирования вышестоящих CLI |
docker compose --profile cliproxyapi up -d |
web |
omniroute-web |
Провайдеры веб-сеансов, которым нужен браузер: gemini-web, claude-web, claude-turnstile (собирает runner-web, Chromium включён) |
docker compose --profile web up -d |
Можно объединить несколько профилей:
docker compose --profile cli --profile cliproxyapi up -d.
Настройка CLI-инструментов хоста при запуске OmniRoute в Docker
Заголовок раздела «Настройка CLI-инструментов хоста при запуске OmniRoute в Docker»omniroute setup-codex, setup-claude, config set <tool> и кнопка
Сохранить конфигурацию на панели управления записывают файлы наподобие ~/.codex/*.config.toml. Эти пути
имеют смысл только на машине, где фактически работает CLI. Если запустить эти команды внутри
контейнера, запись попадёт в собственный домашний каталог контейнера (/home/node —
образ запускается с USER node), откуда ни один CLI на хосте никогда её не прочитает и где она
будет удалена сразу после пересоздания контейнера.
OmniRoute обнаруживает такую ситуацию и вместо сообщения об успехе, результатом которого невозможно
воспользоваться, отклоняет запись и выводит инструкции: CLI завершается с кодом 2, а API отвечает 422
с containerEphemeralTarget: true.
Рекомендуемый вариант: запускать CLI на хосте, а OmniRoute — в Docker
Заголовок раздела «Рекомендуемый вариант: запускать CLI на хосте, а OmniRoute — в Docker»Контейнер предоставляет API, а CLI настраивает ваши инструменты на хосте.
docker compose --profile base up -d
npm install -g omnirouteomniroute connect http://localhost:20128 # подключить CLI к контейнеруomniroute setup-codex # записывает реальную конфигурацию ~/.codex на хостеЭто правильный вариант, если Codex, Claude Code, Cursor или аналогичные инструменты работают на вашем ноутбуке, что соответствует обычной конфигурации.
Альтернатива: bind-монтирование каталогов конфигурации хоста (профиль host)
Заголовок раздела «Альтернатива: bind-монтирование каталогов конфигурации хоста (профиль host)»Если вы хотите, чтобы контейнер самостоятельно записывал конфигурацию на хосте, смонтируйте
каталоги внутрь контейнера и укажите корень точки монтирования в CLI_CONFIG_HOME. В профиле host
это уже настроено:
environment: - CLI_CONFIG_HOME=/host-home - CLI_ALLOW_CONFIG_WRITES=truevolumes: - ~/.codex:/host-home/.codex:rw - ~/.claude:/host-home/.claude:rwИменно bind-монтирование делает путь доверенным: OmniRoute читает
/proc/self/mountinfo и разрешает запись в смонтированные пути (а также в каталоги,
дочерние элементы которых являются точками монтирования, что в точности соответствует приведённой выше структуре /host-home),
продолжая при этом отклонять запись в несмонтированные пути.
Обходной вариант: настройка CLI-инструментов самого контейнера (используйте с осторожностью)
Заголовок раздела «Обходной вариант: настройка CLI-инструментов самого контейнера (используйте с осторожностью)»Если CLI действительно находятся внутри контейнера (профиль cli), запись
является преднамеренной. Передайте --allow-container-write любой команде setup-* или задайте
OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true для сервера. Запись будет выполнена
с предупреждением о том, что она не сохранится после пересоздания контейнера.
Предупреждение о безопасности — профиль
cli+ монтированиеdocker.sock. Профильclibind-монтирует/var/run/docker.sock, чтобы работающий внутри контейнера механизм автоматического обновления мог пересоздать стек через демон хоста (src/lib/system/autoUpdate.tsпроверяет наличие этого сокета и пропускает путь Docker, если он отсутствует). Этот сокет является границей доверия с root-доступом к хосту: всё, что может обращаться к нему, управляет демоном Docker на хосте от имени root — оно может создавать, просматривать, останавливать и удалять любые контейнеры на хосте. Следствия:
- Никогда не открывайте порт профиля
cliдля сети. Публикуйте его на127.0.0.1(ports: "127.0.0.1:${DASHBOARD_PORT:-20128}:...") — доступность профиляcliиз локальной сети превращает любую уязвимость RCE на уровне панели управления в полный захват хоста.- Не bind-монтируйте дополнительные каталоги хоста в профиль
cli. Сокет Docker в сочетании с любым дополнительным монтированием предоставляет контейнеру полный доступ на чтение и запись к вашей файловой системе и конфигурации хоста. Если инструменту нужен доступ к проекту, запускайте его локально с помощью исполняемого файла CLI — не монтируйте проект в контейнерcli.Если автоматическое обновление внутри контейнера не требуется, не включайте профиль
cli(COMPOSE_PROFILES=core,redisили более короткий вариант). Остальные профили не монтируют сокет Docker.Связанная модель угроз для MITM описана в
docs/security/MITM-TPROXY-DECRYPT.md(git; не включается в/docs), а цепочка происхождения исполняемых файловcodex/claude-code/droid/openclaw— вdocs/security/SUPPLY_CHAIN.md.
Сайдкар Redis
Заголовок раздела «Сайдкар Redis»OmniRoute использует Redis для работы распределённого ограничителя частоты запросов и общего кеша. Сервис redis всегда определён в docker-compose.yml (он не привязан к профилю) и запускается вместе с любым другим профилем.
| Параметр | Значение |
|---|---|
| Образ | redis:7-alpine |
| Имя контейнера | omniroute-redis |
| Внутренний порт | 6379 |
| Порт хоста (переопределяемый) | REDIS_PORT (по умолчанию 6379) |
| Адрес хоста (переопределяемый) | REDIS_BIND_HOST (по умолчанию 127.0.0.1) |
| Том | omniroute-redis-data → /data |
| Проверка работоспособности | redis-cli ping (интервал 10 с) |
Связанные переменные окружения:
REDIS_URL— строка подключения, передаваемая приложению (по умолчаниюredis://redis:6379).REDIS_PORT— порт на стороне хоста, сопоставленный с портом контейнера Redis.REDIS_BIND_HOST— интерфейс хоста, на котором публикуется порт. По умолчанию127.0.0.1.
Почему по умолчанию используется loopback-интерфейс: сайдкар запускается без
requirepass, а контейнеры приложения обращаются к нему через сеть compose (redis:6379) — опубликованный порт нужен только для инструментов на стороне хоста (redis-cli, локальный запускnpm run dev). Публикация на0.0.0.0предоставила бы каждому хосту в вашей локальной сети доступ к Redis без аутентификации. Если вы задаётеREDIS_BIND_HOST=0.0.0.0, также добавьте--requirepassвcommand:сервиса.
Отключать Redis не рекомендуется (ограничитель частоты запросов переключится на менее надёжный резервный вариант в памяти). Если это необходимо, удалите или закомментируйте блок сервиса redis: в docker-compose.yml либо уменьшите количество его экземпляров до нуля:
docker compose up -d --scale redis=0Production Compose
Заголовок раздела «Production Compose»Для изолированного production-снимка, работающего параллельно со средой разработки, используйте docker-compose.prod.yml.
| Параметр | Значение |
|---|---|
| Файл | docker-compose.prod.yml |
| Порт панели управления по умолчанию | PROD_DASHBOARD_PORT=20130 (сопоставлен с внутренним ${DASHBOARD_PORT:-20128}) |
| Порт API по умолчанию | PROD_API_PORT=20131 |
| Образ | omniroute:prod (собирается из цели runner-cli) |
| Контейнер Redis | omniroute-redis-prod (redis:8.6.2, выделенный том redis-prod-data) |
| Том данных | omniroute-prod-data (именованный, сохраняется между пересборками) |
| Проверки работоспособности | node healthcheck.mjs + redis-cli ping, при этом depends_on ожидает готовности Redis |
Использование:
# Собрать и запустить production-стекdocker compose -f docker-compose.prod.yml up -d --build
# Просматривать поток журналовdocker compose -f docker-compose.prod.yml logs -f
# Остановить и удалить стек (сохранив тома)docker compose -f docker-compose.prod.yml downProduction-стек работает параллельно с dev-конфигурацией compose (используются разные имена контейнеров, порты и тома), поэтому вы можете продолжать локальную разработку, пока production-среда остаётся запущенной.
Этапы Dockerfile
Заголовок раздела «Этапы Dockerfile»Репозиторий содержит многоэтапный Dockerfile (Dockerfile). Доступны четыре этапа; выберите подходящий target для своего сценария использования.
| Этап | Базовый образ | Назначение |
|---|---|---|
builder |
node:26-trixie-slim |
Устанавливает зависимости (npm ci --legacy-peer-deps) и запускает npm run build (по умолчанию используется Turbopack — см. раздел «Ресурсы во время сборки» ниже) |
runner-base |
node:26-trixie-slim |
Среда выполнения для рабочей среды с автономным выводом Next.js. CLI провайдеров не включены. |
runner-cli |
runner-base |
Добавляет git, docker.io, docker-compose и глобальные CLI: @openai/codex, @anthropic-ai/claude-code, droid, openclaw. Выберите этот этап для агентных рабочих процессов. |
runner-web |
runner-base |
Добавляет Playwright и браузер Chromium (--with-deps) для провайдеров веб-сессий: gemini-web, claude-web, claude-turnstile. Выберите этот этап при использовании этих провайдеров — обычный образ без него завершится ошибкой при выполнении запроса (см. примечание о -web в разделе «Каналы выпуска»). |
Сборка конкретного целевого этапа вручную:
docker build --target runner-base -t omniroute:base .docker build --target runner-cli -t omniroute:cli .docker build --target runner-web -t omniroute:web .Ресурсы во время сборки
Заголовок раздела «Ресурсы во время сборки»Три аргумента сборки определяют ресурсоёмкость этапа builder. Они применяются только во время сборки —
OMNIROUTE_MEMORY_MB (см. ниже) является отдельным параметром среды выполнения.
| Аргумент сборки | По умолчанию | Эффект |
|---|---|---|
OMNIROUTE_USE_TURBOPACK |
1 |
Значение 0 включает сборку с помощью webpack. Меньше пиковое потребление памяти, но ниже скорость. |
OMNIROUTE_BUILD_MEMORY_MB |
6144 |
Предельный размер кучи V8 (--max-old-space-size) для запускаемого процесса next build. |
OMNIROUTE_BUILD_WORKERS |
2 |
Передаёт значение в CIRCLE_NODE_TOTAL; Next вычисляет workers = N - 1 для сбора данных страниц. |
OMNIROUTE_BUILD_WORKERS следует увеличивать на мощной системе сборки, и именно его
нужно проверить в первую очередь, если сборка в условиях ограниченных ресурсов завершается
после ✓ Compiled successfully. Каждый процесс обработки данных страниц выполняется
в отдельном процессе, как и родительский процесс next build; воспроизведение на рабочем
VPS (проблема #7518) показало, что пиковый RSS каждого процесса составляет ~4.5 GB
независимо от флага кучи NODE_OPTIONS (Turbopack выполняет компиляцию в нативной памяти/Rust
за пределами кучи V8). Значение по умолчанию 2 (→ 1 рабочий процесс, всего 2 процесса)
рассчитано на размещённые в GitHub исполнители с 16 GB памяти и 4 vCPU, используемые
конвейером публикации. При значении 8 (→ 7 рабочих процессов) у такого исполнителя
закончилась память, и buildkit завершил этап с ошибкой
ResourceExhausted: ... cannot allocate memory; значение 3 (→ 2 рабочих процесса)
также не уложилось в лимит после прямого измерения RSS каждого процесса вместо расчётной
оценки. tests/unit/docker-build-memory-budget.test.ts выполняет расчёты на основе
измеренного значения и завершается ошибкой, если какой-либо из параметров превышает
возможности исполнителя.
Turbopack выполняет компиляцию в нативной памяти Rust, расположенной за пределами
кучи V8, поэтому OMNIROUTE_BUILD_MEMORY_MB её не ограничивает. На хосте с ограничением
памяти сборка затем принудительно завершается OOM-механизмом посредством SIGKILL вообще без
текста ошибки — она просто останавливается посреди Creating an optimized production build,
что больше похоже на зависание, чем на нехватку памяти. Если ресурсы хоста сборки ограничены,
смените сборщик:
docker build --target runner-base \ --build-arg OMNIROUTE_USE_TURBOPACK=0 \ -t omniroute:base .Параметр webpackBuildWorker включён, поэтому next build запускает родительский
и рабочий процесс, каждый из которых отдельно учитывает OMNIROUTE_BUILD_MEMORY_MB.
Устанавливайте лимит контейнера примерно вдвое выше этого значения, а не равным ему.
Результаты измерений для этого дерева (--target runner-base, OMNIROUTE_BUILD_MEMORY_MB=6144):
| Сборщик | Лимит контейнера | Результат |
|---|---|---|
| Turbopack | 8 GiB / 16 GiB | OOM-завершение при обоих лимитах, без сообщений |
| webpack | 8 GiB | рабочий процесс сборки завершён сигналом SIGKILL |
| webpack | 12 GiB | успешно, пиковое потребление составило 11.1 GiB |
Значения по умолчанию среды выполнения
Заголовок раздела «Значения по умолчанию среды выполнения»Значения по умолчанию, экспортируемые runner-base: PORT=20128, HOSTNAME=0.0.0.0, OMNIROUTE_MEMORY_MB=1024, NODE_OPTIONS=--max-old-space-size=1024, DATA_DIR=/app/data, OMNIROUTE_MIGRATIONS_DIR=/app/migrations.
Поведение памяти в Docker:
- Образ задаёт
OMNIROUTE_MEMORY_MB=1024и на его основе формируетNODE_OPTIONS=--max-old-space-size=1024. - Фактический серверный процесс запускается автономным загрузчиком, который считывает
OMNIROUTE_MEMORY_MBи добавляет--max-old-space-size=<OMNIROUTE_MEMORY_MB>. - Node использует последнее повторяющееся значение
--max-old-space-size, поэтому параметрOMNIROUTE_MEMORY_MBопределяет фактический лимит кучи в Docker. - Поскольку образ всегда задаёт этот параметр, собственное резервное значение загрузчика, рассчитанное на основе объёма RAM, в Docker никогда не применяется. Явно увеличьте его с учётом рабочей нагрузки (см. таблицу ниже).
2048всё ещё недостаточно для запросов агентов программирования к/v1/responses.
Оперативная память для агентов программирования
Заголовок раздела «Оперативная память для агентов программирования»Значение Docker по умолчанию, равное 1 ГиБ, — это минимальный объём для панели управления и простых чатов, а не конфигурация для промышленной эксплуатации. Длинные тела запросов POST /v1/responses (сотни сообщений, десятки инструментов) во время сжатия удерживают в памяти несколько графов. Два параллельных запроса объёмом около 3 МиБ / 750 тыс. токенов приводили к аварийному завершению V8 при 12 ГиБ old-space (FATAL ERROR: Reached heap limit), а также к OOM в cgroup с лимитом 16 ГиБ. См. #7849.
Устанавливайте лимит cgroup --memory выше размера кучи — нативные буферы, SQLite и промежуточные данные сжатия размещаются за пределами V8.
| Рабочая нагрузка | OMNIROUTE_MEMORY_MB |
Контейнер / cgroup | Примечания |
|---|---|---|---|
| Панель управления, один простой чат | 1024 (по умолчанию в образе) |
≥2 ГиБ | |
| Один агент программирования (Claude/Codex/Grok) | 8192 |
≥10 ГиБ | Типичный одиночный сеанс /v1/responses |
Два параллельных длинных запроса /v1/responses |
10240–12288 |
≥12–16 ГиБ | Зафиксировано аварийное завершение V8 при куче около 12 ГиБ |
| Три и более параллельных длинных контекста | не используйте в одном процессе | последовательная обработка / больше RAM | По умолчанию допускается 1 ресурсоёмкий запрос в обработке; увеличение этого значения без дополнительной RAM снова приводит к аварийному завершению |
При запуске omniroute serve на физическом сервере рассчитывается около 35% от объёма RAM (с ограничением диапазоном [512, 4096]), если OMNIROUTE_MEMORY_MB не задана. Docker всегда задаёт значение 1024, поэтому в официальном образе этот расчёт никогда не выполняется.
docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \ -e OMNIROUTE_MEMORY_MB=8192 --memory=10g \ -p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latestКритические переменные окружения
Заголовок раздела «Критические переменные окружения»Помимо значений по умолчанию, описанных в ENVIRONMENT.md, при запуске в Docker наиболее важны следующие переменные:
| Переменная | Назначение | Значение по умолчанию |
|---|---|---|
OMNIROUTE_WS_BRIDGE_SECRET |
Общий секрет для моста WebSocket. Обязателен в рабочей среде — задайте надежную случайную строку. | не задано (необходимо указать) |
REDIS_URL |
Строка подключения к серверной части ограничителя частоты запросов / кеша | redis://redis:6379 |
REDIS_PORT |
Порт хоста для входящего в комплект контейнера Redis | 6379 |
REDIS_BIND_HOST |
Интерфейс хоста, на котором публикуется порт входящего в комплект Redis (кольцевой интерфейс, если не добавлена AUTH) | 127.0.0.1 |
AUTO_UPDATE_HOST_REPO_DIR |
Путь на хосте, подключаемый к профилю cli по адресу /workspace/omniroute для рабочих процессов самообновления |
. (текущий каталог) |
OMNIROUTE_MEMORY_MB |
Максимальный размер кучи Node во время выполнения для автономного сервера Docker; переопределяет указанное выше значение по умолчанию из образа. Для агентов программирования: 8192+ (см. оперативная память среды выполнения). |
1024 |
DASHBOARD_PORT / API_PORT |
Переопределяют опубликованные порты панели управления (20128) и API (20129) | 20128 / 20129 |
APP_BIND_HOST |
Интерфейс хоста, на котором docker-compose публикует порты панели управления/API/live-WS. При REQUIRE_API_KEY=false (значение по умолчанию) 0.0.0.0 открывает анонимный прокси /v1 для локальной сети — расширяйте доступ только при REQUIRE_API_KEY=true или при наличии обратного прокси перед приложением. |
127.0.0.1 |
CLIPROXY_BIND_HOST |
Интерфейс хоста, на котором docker-compose публикует дополнительный контейнер cliproxyapi; его том данных содержит учетные данные провайдера. |
127.0.0.1 |
OMNIROUTE_PLUGINS_DIR |
Каталог, который сканер плагинов среды выполнения читает и использует для установки. Задайте его, если плагины подключаются через bind mount: значение по умолчанию зависит от HOME, который не обязательно экспортируется образом. |
~/.omniroute/plugins |
OMNIROUTE_BASE_PATH |
Подпуть URL, если приложение публикуется за обратным прокси (например, /omniroute) |
(пусто = корень) |
NEXT_PUBLIC_BASE_URL |
Публичный источник браузера, включающий подпуть (например, https://host/omniroute) |
не задано |
PROD_DASHBOARD_PORT |
Порт панели управления на стороне хоста для docker-compose.prod.yml |
20130 |
CLIPROXYAPI_PORT |
Порт на стороне хоста для дополнительного контейнера cliproxyapi |
8317 |
Обратный прокси на подпути (Traefik / nginx)
Заголовок раздела «Обратный прокси на подпути (Traefik / nginx)»Значение basePath Next.js компилируется в автономный пакет. OmniRoute записывает встроенное
значение в сигнальный файл в корне приложения (записывается во время npm run build; считывается
scripts/docker/ensure-docker-base-path.mjs) и сравнивает его с
OMNIROUTE_BASE_PATH при запуске контейнера. Если значения различаются, а образ был
собран для корня домена, точка входа изменяет автономные манифесты,
встроенные литералы basePath/assetPrefix (Next 16 формирует URL-адреса ресурсов SSR
только из assetPrefix — патчер добавляет в него подпуть), встроенные
URL-адреса ресурсов /_next/static (манифесты клиентских ссылок, импорты медиафайлов,
предварительно отрендеренные страницы ошибок) и клиентскую прослойку process.env перед запуском
node dev/run-standalone.mjs.
Сборка с помощью Compose (рекомендуется)
Заголовок раздела «Сборка с помощью Compose (рекомендуется)»Задайте обе переменные в .env, затем пересоберите образ, чтобы настройки образа и среды выполнения совпадали:
OMNIROUTE_BASE_PATH=/omnirouteNEXT_PUBLIC_BASE_URL=https://myhostname.example.com/omniroutedocker compose --profile base up -d --builddocker-compose.yml передаёт OMNIROUTE_BASE_PATH как аргумент сборки Docker и как
переменную среды выполнения.
Предварительно собранный корневой образ + подпуть среды выполнения
Заголовок раздела «Предварительно собранный корневой образ + подпуть среды выполнения»Опубликованные образы diegosouzapw/omniroute:* собраны для корня домена. Тем не менее
можно задать OMNIROUTE_BASE_PATH во время выполнения; контейнер однократно исправит пакет при запуске.
Укажите также соответствующий публичный источник:
services: omniroute: image: diegosouzapw/omniroute:latest environment: OMNIROUTE_BASE_PATH: /omniroute NEXT_PUBLIC_BASE_URL: https://myhostname.example.com/omnirouteНастройте обратный прокси так, чтобы он перенаправлял полный внешний путь (не удаляйте
префикс). Traefik должен направлять PathPrefix(/omniroute) в контейнер без
StripPrefix, чтобы Next.js получал /omniroute/... и отдавал ресурсы из
/omniroute/_next/....
Проверка работоспособности Docker обращается к облегчённой конечной точке жизненного цикла /healthz с префиксом
активного значения OMNIROUTE_BASE_PATH. /api/monitoring/health остаётся доступной для
диагностики вручную или с помощью панели мониторинга; чтобы снова направить HEALTHCHECK контейнера на неё (например,
для углублённой проверки работоспособности), задайте OMNIROUTE_HEALTHCHECK_PATH=/api/monitoring/health.
Этот путь выполняет углублённую проверку (БД + сводка мониторинга) — она подходит для
нечастого HEALTHCHECK Docker, если вы решите снова её включить, но не для интервалов
livenessProbe Kubernetes.
Для оркестраторов (Kubernetes, Nomad и т. д.):
| Проверка | Предпочтительно | Не рекомендуется |
|---|---|---|
| Жизнеспособность | HTTP GET /livez или TCP на основном порту (PORT, по умолчанию 20128) |
/api/monitoring/health для проверки жизнеспособности |
| Готовность | HTTP GET /healthz |
Короткие тайм-ауты, при которых занятый цикл событий считается отказавшим |
| Углублённая / blackbox | /api/monitoring/health |
— |
/healthz сообщает о состоянии жизненного цикла процесса (ok / starting / stopping). /livez
проверяет только работу процесса (возвращает 200, если обработчик может выполняться; ожидания
готовности нет). Обе проверки по-прежнему выполняются в том же цикле событий Node, что и обработка запросов, поэтому
ресурсоёмкая обработка каталога или сжатие могут задерживать их — занятость ≠ отказ. Если HTTP-проверки
завершаются по тайм-ауту, для проверки жизнеспособности предпочтительно использовать TCP. Полное руководство по проверкам:
Руководство по мониторингу — рекомендации по проверкам Kubernetes.
Docker Compose с Caddy (автоматический TLS для HTTPS)
Заголовок раздела «Docker Compose с Caddy (автоматический TLS для HTTPS)»OmniRoute можно безопасно опубликовать с помощью автоматической настройки SSL в Caddy. Убедитесь, что DNS-запись A вашего домена указывает на IP-адрес вашего сервера.
services: omniroute: image: diegosouzapw/omniroute:latest container_name: omniroute restart: unless-stopped volumes: - omniroute-data:/app/data environment: - PORT=20128 # Публичный адрес для обратных вызовов OAuth, ссылок панели управления и создаваемых публичных URL. - NEXT_PUBLIC_BASE_URL=https://your-domain.com # Внутренний межсерверный URL для запланированных заданий и запросов к самому сервису. - BASE_URL=http://omniroute:20128 - AUTH_COOKIE_SECURE=true
caddy: image: caddy:latest container_name: caddy restart: unless-stopped ports: - "80:80" - "443:443" command: caddy reverse-proxy --from https://your-domain.com --to http://omniroute:20128
volumes: omniroute-data:Caddy устанавливает стандартные заголовки переадресации для вышестоящего контейнера. OmniRoute использует
NEXT_PUBLIC_BASE_URL в качестве канонического публичного источника для обратных вызовов OAuth и создаваемых публичных
ссылок; аутентифицированные операции записи из панели управления используют запросы того же источника и привязанную к сеансу защиту
CSRF. Включайте OMNIROUTE_TRUST_PROXY только в расширенных конфигурациях, где вы намеренно
хотите, чтобы OmniRoute определял публичный источник по доверенным перенаправленным заголовкам вместо явной
конфигурации.
Быстрый туннель Cloudflare
Заголовок раздела «Быстрый туннель Cloudflare»Поддержка панели управления для развёртываний Docker включает включаемый одним щелчком быстрый туннель Cloudflare в разделе Dashboard → Endpoints. При первом включении cloudflared загружается только при необходимости, запускается временный туннель к вашему текущему эндпоинту /v1, а созданный URL https://*.trycloudflare.com/v1 отображается непосредственно под вашим обычным публичным URL.
Панели туннелей эндпоинта (Cloudflare, Tailscale, ngrok) можно показывать или скрывать в разделе Settings → Appearance, не изменяя состояние активного туннеля.
Примечания о туннеле
Заголовок раздела «Примечания о туннеле»- URL быстрых туннелей являются временными и меняются после каждого перезапуска.
- Быстрые туннели не восстанавливаются автоматически после перезапуска OmniRoute или контейнера. При необходимости повторно включите их через панель управления.
- Управляемая установка в настоящее время поддерживает Linux, macOS и Windows на
x64/arm64. - Управляемые быстрые туннели по умолчанию используют транспорт HTTP/2, чтобы избежать многочисленных предупреждений о размере UDP-буфера QUIC в контейнерных средах с ограниченными ресурсами. Установите
CLOUDFLARED_PROTOCOL=quicилиauto, если хотите использовать другой транспорт. - Образы Docker включают системные корневые сертификаты ЦС и передают их управляемому
cloudflared, что предотвращает ошибки доверия TLS при инициализации туннеля внутри контейнера. - Установите
CLOUDFLARED_BIN=/absolute/path/to/cloudflared, если хотите, чтобы OmniRoute использовал существующий исполняемый файл вместо его загрузки.
Теги образов
Заголовок раздела «Теги образов»| Образ | Тег | Размер | Описание |
|---|---|---|---|
diegosouzapw/omniroute |
latest |
~250MB | Самая новая опубликованная стабильная версия SemVer (не git main) |
diegosouzapw/omniroute |
3.8.0 |
~250MB | Закрепляйте теги этого типа для GitOps |
Мультиплатформенный манифест: нативные linux/amd64 + linux/arm64 (Apple Silicon, AWS Graviton, Raspberry Pi). Docker автоматически выбирает подходящую архитектуру; передайте --platform linux/amd64, если необходимо принудительно использовать эмуляцию AMD64 на хостах ARM.
Каналы выпусков
Заголовок раздела «Каналы выпусков»OmniRoute публикует отдельные Docker-каналы для стабильных выпусков, тестирования активной ветки выпуска и сборок для разработки.
| Канал | Источник | Изменяемость | Рекомендуемое применение |
|---|---|---|---|
:<version> / :<version>-web |
Подписанный/версионированный выпуск | Неизменяемый | Рабочие развертывания с закреплением точного выпуска |
:latest / :latest-web |
Самая новая опубликованная стабильная версия SemVer | Изменяемый указатель на стабильную версию | Следует за стабильными выпусками после задания публикации SemVer — не отслеживает main или невыпущенные коммиты release/v* |
:next / :next-web |
Текущая ветка release/v* по умолчанию |
Изменяемый указатель на предварительный выпуск | Тестирование исправлений, которые уже попали в активную ветку выпуска, но еще не вошли в стабильный выпуск |
:main / :main-web |
Ветка main |
Изменяемый указатель на версию для разработки | Только для разработки и интеграционного тестирования |
Провайдеры веб-сеансов: образы -web
Заголовок раздела «Провайдеры веб-сеансов: образы -web»Для каждого указанного выше канала также существует тег -web (:latest-web, :<version>-web, :next-web, :main-web), собранный из этапа runner-web — это тот же образ, но с Playwright и браузером Chromium. Обычный образ поставляется без Chromium; он необходим для gemini-web, claude-web и claude-turnstile.
Ошибка возникает не при запуске, а позже: эти провайдеры отображают свои модели и показываются на панели как подключенные, и только первый запрос завершается ошибкой
[500]: Failed to load external module playwright: Error: Cannot find module'/app/node_modules/playwright/node_modules/playwright-core/browsers.json'Если вы используете эти провайдеры, загрузите тег -web того канала, на котором уже находитесь, — больше ничего менять не нужно. При установке через npm/CLI (без образа Docker) недостающим компонентом является исполняемый файл браузера: выполните npx playwright install chromium на хосте.
Использование канала предварительных выпусков
Заголовок раздела «Использование канала предварительных выпусков»Канал next пересобирается при каждой отправке изменений в текущую ветку release/v* по умолчанию и публикуется как для AMD64, так и для ARM64. Более старые ветки сопровождения не могут его перезаписать. Этот канал предоставляет доступный для загрузки образ с исправлениями, которые были объединены с активной веткой выпуска до создания следующего стабильного тега.
docker pull diegosouzapw/omniroute:nextdocker pull diegosouzapw/omniroute:next-webДля Docker Compose переопределите тег образа, используемый выбранным профилем, затем загрузите образ и пересоздайте сервис:
services: omniroute: image: diegosouzapw/omniroute:nextdocker compose pulldocker compose up -dБезопасность и откат
Заголовок раздела «Безопасность и откат»next — это плавающий канал предварительных выпусков. Он может измениться при любой отправке изменений в активную ветку выпуска и не поддерживается для использования в рабочей среде. При оценке конкретной сборки закрепите дайджест образа:
docker pull diegosouzapw/omniroute:nextdocker image inspect diegosouzapw/omniroute:next --format '{{index .RepoDigests 0}}'Перед тестированием создайте резервную копию тома данных OmniRoute или каталога данных, подключенного через bind mount. Для отката восстановите ранее использовавшуюся стабильную версию или дайджест и пересоздайте контейнер:
docker pull diegosouzapw/omniroute:<stable-version>docker compose up -dСборка из ветки выпуска никогда не может изменить latest; стабильный указатель может быть обновлен только подходящей стабильной семантической версией. Для образов next сохраняются проверка образа выпуска и блокирующий шлюз для уязвимостей уровня CRITICAL.
latest не гарантирует актуальность относительно git. Объединенные исправления в main или активной ветке release/v* не попадают в :latest, пока не будет опубликован образ стабильной версии SemVer и задание публикации не обновит :latest (с тем же дайджестом, что и у этой версии SemVer). Если latest кажется замороженным, хотя исправление уже отображается на GitHub, загрузите :next, чтобы протестировать ветку выпуска, или дождитесь тега SemVer.
| Что вам нужно | Что использовать |
|---|---|
| GitOps / рабочая среда без самопроизвольного обновления | Закрепите :X.Y.Z (или дайджест образа) |
| Следовать за опубликованными стабильными версиями и пересоздавать контейнер при каждом выпуске | :latest |
Тестировать невыпущенные коммиты release/v* |
:next (не для рабочей среды) |
Тестировать main |
:main (не для рабочей среды) |
Доступность: SQLite по умолчанию работает с одной репликой
Заголовок раздела «Доступность: SQLite по умолчанию работает с одной репликой»Стандартное развёртывание OmniRoute в Docker / Kubernetes — это один процесс Node + один процесс записи SQLite. Высокая доступность в такой топологии не поддерживается.
| Ограничение | Последствие |
|---|---|
| Один процесс записи | Не запускайте несколько реплик с одним и тем же файлом SQLite. Это приведёт к повреждению БД. |
| Пересоздание / перезапуск / завершение через HEALTHCHECK | Полная недоступность активных SSE-соединений, сеансов панели управления и состояния в памяти. Все подключённые клиенты отключаются. Новые запросы в период отсутствия конечных точек получают от обратного прокси 502 Bad Gateway: Unknown error, а не JSON от OmniRoute — клиенты не могут отличить это от сбоя провайдера (#11015). |
Один цикл событий с /healthz |
Загруженная операция с каталогом или цикл сжатия могут задержать проверки; короткий тайм-аут после этого перезапустит единственную реплику. |
Матрица проверок (см. также рекомендации по проверкам Kubernetes):
| Проверка | Цель | Не используйте |
|---|---|---|
| Проверка жизнеспособности | TCP на PORT (по умолчанию 20128) или мягкая HTTP-проверка /healthz |
/api/monitoring/health |
| Проверка готовности | HTTP GET /healthz |
Короткие тайм-ауты, принимающие занятый цикл событий за отказ |
| Глубокая / для людей | /api/monitoring/health |
Автоматическую проверку жизнеспособности kubelet |
Обновления: ожидайте разрыва каждого сеанса. По возможности предварительно отключите клиентов; при использовании SQLite по умолчанию последовательное обновление недоступно. Сочетание Compose restart: unless-stopped и Docker HEALTHCHECK также заменит единственный процесс, когда контейнер перейдёт в состояние Unhealthy, — с тем же масштабом последствий.
Фрагмент конфигурации Kubernetes для одной реплики (требуется Recreate; не увеличивайте replicas при использовании одного файла SQLite):
spec: replicas: 1 strategy: type: Recreate template: spec: terminationGracePeriodSeconds: 90 containers: - name: omniroute lifecycle: preStop: exec: command: ["/bin/sleep", "15"] readinessProbe: httpGet: path: /healthz port: 20128 periodSeconds: 5 livenessProbe: tcpSocket: port: 20128 periodSeconds: 20Задержка preStop позволяет kube удалить конечные точки Service до SIGTERM, чтобы новый трафик перестал поступать в завершающийся процесс. Активные SSE-соединения /v1/responses обслуживаются до истечения SHUTDOWN_TIMEOUT_MS (по умолчанию 30 с) с помощью тяжеловесных разрешений на приём запросов (#11015). Новые запросы, которые всё же достигают процесса, получают 503 + Retry-After: 5. Период отсутствия конечных точек при Recreate до перехода замены в состояние Ready остаётся полной недоступностью — это свойство топологии SQLite, а не ошибка настройки проверок.
Внешний Postgres / многопроцессорная HA-конфигурация не является документированным стандартным вариантом. Если вам нужна HA, используйте одну реплику либо топологию, которую проект отдельно протестировал и задокументировал. Работа над Postgres/MySQL ведётся в #8075. Пока она не завершена, единственный поддерживаемый способ увеличить пропускную способность для крупных запросов /v1/responses — использовать N независимых процессов (см. следующий раздел), а не replicas > 1 на одном томе.
Горизонтальное масштабирование: N независимых процессов
Заголовок раздела «Горизонтальное масштабирование: N независимых процессов»Один процесс Node — это одна куча V8. Два перекрывающихся запроса агента программирования POST /v1/responses объёмом ~3 MiB / ~750 тыс. токенов (RTK + Caveman) аварийно завершают работу этой кучи примерно при 12 Gi (FATAL ERROR: Reached heap limit) и могут вызвать OOM в cgroup размером 16 Gi. См. #7849. Этот результат измерения — предупреждение об ограничении памяти, а не жёсткий предел продукта в два одновременных длительных запроса /v1/responses. Допуск ресурсоёмких запросов чата регулируется автоматически вычисляемым бюджетом входящих байтов (OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES, src/shared/middleware/admissionBudget.ts), рассчитанным исходя из того же предела V8/cgroup. Увеличение этого значения вручную (или установка устаревшего ограничения по числу запросов OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT) в уже настроенном по размеру процессе снова приводит к аварийному завершению. Небольшие запросы чата, /healthz, /v1/models и MCP не входят в это ограничение.
Один процесс: более двух длительных запросов /v1/responses
Заголовок раздела «Один процесс: более двух длительных запросов /v1/responses»Исправный процесс (куча ниже OMNIROUTE_CHAT_ADMISSION_HEAP_SHED_RATIO, по умолчанию 0.75) может выполнять более двух одновременных длительных запросов POST /v1/responses, если в общепроцессном бюджете байтов выполняющихся запросов (OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES / #10110) ещё остаётся место. Тела запросов размером не менее OMNIROUTE_CHAT_LARGE_BODY_BYTES (по умолчанию 256 KiB) получают ту же ресурсоёмкую аренду, что и запросы со сложной структурой, и используют тот же механизм обхода tryAcquireHealthyHeadroom из #10437 (OMNIROUTE_CHAT_ADMISSION_HEALTHY_HEADROOM). Десятки одновременных длительных SSE-клиентов (операторам часто требуется 40–50) — это вопрос бюджета памяти: необходимо подобрать размер кучи, количество основных и резервных слотов, а также OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES. Это не жёсткое ограничение продукта «не более 2». При нехватке памяти процесс по-прежнему отклоняет нагрузку с допускающим повторную попытку кодом 503, чтобы проблема #7849 не возникла снова.
Чтобы умножить количество куч (независимых старых пространств V8) сегодня:
| Следует | Не следует |
|---|---|
Запускать N контейнеров/подов, каждый со своим собственным DATA_DIR / томом |
Устанавливать replicas > 1 для одного файла SQLite |
| Рассчитывать количество ресурсоёмких выполняющихся запросов и резервных слотов исходя из кучи / бюджета байтов выполняющихся запросов; 1–2 — консервативное значение по умолчанию из #7849, а не жёсткий предел продукта | Выделять одному процессу в 8 раз больше RAM и снимать ограничение по количеству |
Необязательно: QUOTA_STORE_DRIVER=redis + QUOTA_STORE_REDIS_URL для общих счётчиков квот |
Считать Redis общей SQLite — это не так |
| Дублировать секреты провайдеров в каждом экземпляре (или согласиться с раздельными панелями мониторинга) | Ожидать одну панель мониторинга / один журнал вызовов для всех экземпляров |
| Размещать впереди любой балансировщик нагрузки; достаточно привязки по ключу API или сеансу | Требовать специализированное промежуточное ПО конкретного поставщика с учётом размера |
Оборудование: количество одновременных длительных запросов /v1/responses на экземпляр — это вопрос бюджета памяти (куча + байты выполняющихся запросов / #10110). N независимых DATA_DIR всё равно означают N куч: RAM хоста должна обеспечивать N × cgroup, а не «один под на 16 Gi с N=8». Никогда не используйте replicas > 1 для одного файла SQLite.
Пример Compose (две кучи, два тома — не deploy.replicas: 2):
services: omniroute-a: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-a-data:/app/data] ports: ["20128:20128"] omniroute-b: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-b-data:/app/data] ports: ["20138:20128"]volumes: omniroute-a-data: omniroute-b-data:Повышение плотности внутри процесса (вынесение сжатия за пределы HTTP-изолята) рассматривается в #11023. Один логический кластер с общим долговременным состоянием рассматривается в #8075.
Важные примечания
Заголовок раздела «Важные примечания»- Режим WAL в SQLite: необходимо дождаться завершения
docker stop, чтобы OmniRoute успел записать последние изменения обратно вstorage.sqliteс помощью контрольной точки. Включённые файлы Compose уже задают 40-секундный льготный период остановки. Если вы запускаете образ напрямую, используйте--stop-timeout 40. DISABLE_SQLITE_AUTO_BACKUP: установите значениеtrue, если регулярные резервные копии и резервные копии перед записью создаются внешними средствами. Для миграций существующих баз данных по-прежнему требуется отдельный надёжный снимок безопасности и защита от массовой миграции.- Сохранение данных: всегда подключайте том к
/app/data, чтобы база данных, ключи и конфигурации сохранялись при перезапусках контейнера. - Настройка порта: переопределите переменную окружения
PORT, чтобы изменить порт20128, используемый по умолчанию.
См. также
Заголовок раздела «См. также»- Руководство по развёртыванию на виртуальной машине — настройка виртуальной машины, nginx и Cloudflare
- Руководство по развёртыванию на Fly.io — развёртывание на Fly.io
- Настройка переменных окружения — полный справочник по
.env
HagiCode
HagiCode — агентная среда разработки со структурированными процессами, параллельным выполнением несколькими агентами и интерфейсами Hero Dungeon.
Превращайте идеи в полезное ПО с более умным, быстрым и увлекательным агентным рабочим процессом.

- SmartСтруктурированные процессы превращают намерение в исполнимый путь от идеи до готового изменения.
- EfficientМультиагентные процессы параллельно продвигают исследование, реализацию и проверку.
- FunHero Dungeon делает длительную совместную разработку наглядной и увлекательной.