Appearance
Установка сервисов
Разворачивание prod-стека Unishift Platform из готовых образов. CLI ush скачивает конфигурацию с storage.unishift.ru, сам генерирует все секреты, накатывает миграции и поднимает сервисы.
Требования
На сервере должны быть установлены:
| Компонент | Проверка |
|---|---|
| Docker Engine | docker info |
| Docker Compose v2 (плагин) | docker compose version |
| curl | curl --version (только для bootstrap install.sh) |
Пользователь, от которого запускается установка, должен иметь доступ к docker-демону (входить в группу docker либо запускать под root).
Установщик сам проверяет наличие Docker и останавливается с понятной ошибкой, если чего-то не хватает (например: docker is required but was not found in PATH). На чистом VPS Docker ещё не установлен — сначала подготовьте сервер.
Сколько нужно железа
Требования к CPU, RAM и диску под конкретное число пользователей — в разделе Sizing, схемы размещения на одном и нескольких узлах — в референсных архитектурах.
Подготовка чистого VPS
Инструкция рассчитана на свежий Linux-сервер (Ubuntu / Debian и аналоги). Нужны права root или sudo.
1. Базовые утилиты
curl обычно уже есть. Если нет:
bash
# Debian / Ubuntu
apt-get update
apt-get install -y curl ca-certificates2. Установка Docker Engine и Compose v2
Официальный скрипт Docker ставит Engine и плагин Compose одной командой:
bash
curl -fsSL https://get.docker.com | shПроверка:
bash
docker info
docker compose versionДемон должен отвечать без ошибок. Если docker есть, а docker info жалуется на права — либо работайте под root, либо добавьте пользователя в группу и перелогиньтесь:
bash
usermod -aG docker "$USER"
# затем новый SSH-сеанс / newgrp dockerАльтернатива: пакеты репозитория Docker
Вместо get.docker.com можно поставить пакеты вручную по официальной инструкции для вашего дистрибутива. Нужны как минимум docker-ce, docker-ce-cli, containerd.io и docker-compose-plugin (команда docker compose, не отдельный docker-compose v1).
После проверки Docker переходите к быстрой установке ниже.
Быстрая установка
Одна команда ставит CLI ush (если его нет) и разворачивает стек: файлы, секреты, миграции, контейнеры.
bash
curl -fsSL https://storage.unishift.ru/services/prod/install.sh | bashinstall.sh — только bootstrap. Дальше стеком управляет ush platform; bash-скрипты в каталог установки не кладутся.
На чистом VPS без Docker команда завершится ошибкой — сначала выполните подготовку сервера.
Если ush уже в PATH:
bash
ush platform install
ush platform install --public-host 203.0.113.10
ush platform install --public-host app.example.com --public-scheme https
ush platform install --dir /srv/unishiftПо умолчанию каталог — /opt/unishift. Там остаются docker-compose.yaml, конфиги (postgres/, centrifugo/, searxng/) и сгенерированный .env.
Те же параметры можно передать переменными в bash при bootstrap (не в curl):
bash
curl -fsSL https://storage.unishift.ru/services/prod/install.sh \
| PUBLIC_HOST=203.0.113.10 bash
curl -fsSL https://storage.unishift.ru/services/prod/install.sh \
| PUBLIC_HOST=app.example.com PUBLIC_SCHEME=https bash
curl -fsSL https://storage.unishift.ru/services/prod/install.sh \
| INSTALL_DIR=/srv/unishift bashПосле установки публичный адрес меняется так (секреты в .env не трогает):
bash
ush platform update --public-host 203.0.113.10
ush platform update --public-host app.example.com --public-scheme https| Переменная / флаг | Назначение | По умолчанию |
|---|---|---|
INSTALL_DIR / --dir | Куда установить | /opt/unishift |
BASE_URL / --base-url | Откуда качать файлы | …/services/prod |
REGISTRY / --registry | Реестр образов | leggnom |
TAG / --tag | Тег образов | latest |
PUBLIC_HOST / --public-host | Публичный IP/домен (для UI и WebSocket) | localhost |
PUBLIC_SCHEME / --public-scheme | http или https | http |
WEB_BASE_URL / --web-base-url | URL веб-клиента | из PUBLIC_* (см. ниже) |
CENTRIFUGO_WS_URL / --centrifugo-ws-url | WebSocket URL для браузера | из PUBLIC_* (см. ниже) |
CENTRIFUGO_ALLOWED_ORIGINS / --centrifugo-allowed-origins | Origin фронтенда (через пробел) | из PUBLIC_* (см. ниже) |
Как собираются URL, если их не задали явно:
PUBLIC_SCHEME | WEB_BASE_URL | CENTRIFUGO_WS_URL |
|---|---|---|
http (по умолчанию) | http://HOST:18080 | ws://HOST:18100/connection/websocket |
https | https://HOST | wss://HOST/connection/websocket |
Для https установщик предполагает reverse proxy на 443 (UI и Centrifugo на одном хосте). Если порты другие — задайте WEB_BASE_URL, CENTRIFUGO_WS_URL и CENTRIFUGO_ALLOWED_ORIGINS явно.
Что разворачивается
Полный набор модулей платформы плюс инфраструктура. Мониторинг (Prometheus и экспортеры) в prod не входит — он есть только в dev-стеке (devops/dev).
Модули (25): client, concierge_web, gateway, auth, spaces, documents, task-tracker, notifications, messaging, collatio, concierge, mcp-gateway, command-manager, scheduler, storage, env-manager, flow-manager, spark-grid, ai-router, guard, notebooks, content-extract, nats-bridge, proxy-manager, voice — 23 Go-сервиса и два веб-фронта.
Data Tables, Dashboards и Data Catalog пока не входят в prod-каталог services.yaml (работают в dev-стеке devops/dev).
Инфраструктура: postgres, nats, minio (+ однократный job minio-init), centrifugo, searxng.
Инференс LLM в стек не входит: адрес и имя модели задаёт провайдер в AI Router — см. Локальные модели.
Стек запускается под именем проекта unishift-prod — сеть, тома и контейнеры изолированы от других окружений на той же машине.
Секреты
Установщик генерирует их однократно и складывает в INSTALL_DIR/.env с правами 600. Повторный запуск установщика их не трогает.
| Секрет | Назначение |
|---|---|
DB_PASSWORD | Пароль PostgreSQL |
JWT_SECRET | Подпись JWT и токенов Centrifugo |
SESSION_SECRET | Подпись сессий |
ENCRYPTION_KEY | Ключ шифрования Env Manager и SMTP-паролей Notifications (base64 от 32 байт) |
SERVICE_TOKEN | Межсервисные вызовы |
CENTRIFUGO_API_KEY | Серверный HTTP API Centrifugo |
SEARXNG_SECRET | Секрет SearXNG |
MINIO_ROOT_PASSWORD | Пароль MinIO |
Сделайте резервную копию .env
Потеря ENCRYPTION_KEY делает нечитаемыми все значения, сохранённые в Env Manager. Смена DB_PASSWORD на уже инициализированной БД ломает доступ к данным. Скопируйте INSTALL_DIR/.env в надёжное место после установки.
Порты
Публикуются в диапазоне 1xxxx, чтобы не конфликтовать с другими окружениями.
| Сервис | Порт хоста | Env |
|---|---|---|
Веб-клиент (unishift_client_web) | 18080 | CLIENT_PORT |
Concierge SPA (unishift_concierge_web) | 18081 | CONCIERGE_WEB_PORT |
| Gateway | 18090 | GATEWAY_PORT |
| Auth | 18091 | AUTH_PORT |
| Spaces | 18092 | SPACES_PORT |
| Documents | 18093 | DOCUMENTS_PORT |
| Command Manager | 18094 | COMMAND_MANAGER_PORT |
| Scheduler | 18095 | SCHEDULER_PORT |
| Storage | 18096 | STORAGE_PORT |
| Env Manager | 18097 | ENV_MANAGER_PORT |
| Flow Manager | 18099 | FLOW_MANAGER_PORT |
| Centrifugo | 18100 | CENTRIFUGO_PORT |
| AI Router | 18101 | AI_ROUTER_PORT |
| Task Tracker | 18102 | TASK_TRACKER_PORT |
| Notifications | 18103 | NOTIFICATIONS_PORT |
| MCP Gateway | 18104 | MCP_GATEWAY_PORT |
| Data Tables | 18105 | DATA_TABLES_PORT |
| Concierge API | 18106 | CONCIERGE_PORT |
| Messaging | 18107 | MESSAGING_PORT |
| Collatio | 18108 | COLLATIO_PORT |
| Guard | 18110 | GUARD_PORT |
| Notebooks | 18111 | NOTEBOOKS_PORT |
| Content Extract | 18112 | CONTENT_EXTRACT_PORT |
| Proxy Manager (API / forward proxy) | 18114 / 18115 | PROXY_MANAGER_PORT / FORWARD_PROXY_PORT |
| Voice | 18116 | VOICE_PORT |
| SearXNG | 18088 | SEARXNG_PORT |
| Spark Grid | 18087 | SPARK_GRID_PORT |
| PostgreSQL | 15432 | POSTGRES_PORT |
| NATS (клиент / мониторинг) | 14222 / 18222 | NATS_PORT / NATS_MONITOR_PORT |
| MinIO (API / консоль) | 19010 / 19011 | MINIO_PORT / MINIO_CONSOLE_PORT |
Имя env порта веб-клиента — CLIENT_PORT (не CLIENT_WEB): образ называется unishift_client_web, переменная хост-порта — CLIENT_PORT.
Строка Data Tables (18105) — зарезервированная переменная .env: сервис пока не входит в prod-каталог, порт не занимается.
Guard NER sidecar в prod-стек не входит и наружу не публикуется: внутри docker-сети слушает 8111 (как и Notebooks, но это разные контейнеры — конфликта нет). При ручном запуске за пределами compose опубликуйте любой свободный хост-порт.
WebSocket и удалённый доступ
Браузер подключается к Centrifugo напрямую по адресу из CENTRIFUGO_WS_URL (gateway отдаёт его в /api/v1/services). Значение ws://localhost:18100/... работает только если UI открыт на той же машине, где крутится стек.
Если в консоли браузера:
text
WebSocket connection to 'ws://localhost:18100/connection/websocket' failedпоправьте публичный адрес и пересоздайте стек:
bash
ush platform update --public-host 203.0.113.10Порт 18100 должен быть открыт на firewall (или Centrifugo должен быть за reverse proxy с wss://). CENTRIFUGO_ALLOWED_ORIGINS обязан совпадать с Origin страницы (схема + хост + порт UI).
Отдельно: интерактивный терминал и ush connect идут через wss://HOST/proxy/command-manager/... (не Centrifugo). На reverse proxy для location / (или /proxy/) нужны proxy_http_version 1.1, Upgrade/Connection и длинный proxy_read_timeout — иначе handshake даёт 400 Bad Request, а UI пишет «Агент не в сети». Пример — reference-architecture.md.
Логирование
В prod по умолчанию LOG_LEVEL=error и LOG_FORMAT=text — в логи попадают только ошибки, обычным текстом (не JSON). Для отладки поднимите уровень в .env:
env
LOG_LEVEL=info # debug | info | warn | error | fatal | panic
LOG_FORMAT=json # text | jsonУправление
Каталог по умолчанию — /opt/unishift (--dir, если другой):
bash
ush platform update # файлы со storage + migrate + up -d
ush platform update --public-host <IP>
ush platform upgrade # обновить образы установленных сервисов
ush platform services # таблица: направление, статус, образ
ush platform ps # статус сервисов
ush platform logs -f # логи в реальном времени
ush platform logs -f auth # логи одного сервиса
ush platform config show # .env с маскированными секретами
ush platform enable guard # включить сервис (+ зависимости)
ush platform down # остановить стек (тома сохраняются)
ush platform up # поднять снова
ush platform migrate # только миграции и бакет MinIO
ush platform doctor # самодиагностика: Docker, порты, секреты, БД
ush platform backup # полный бэкап Postgres, MinIO и .env
ush platform restore <archive> --yes # восстановление из бэкапаСправка по флагам: ush platform --help и CLI.
Резервное копирование и восстановление
Для создания снимка баз данных и хранилища перед обновлениями или переносом:
bash
ush platform backup # сохранит в unishift-backup-<timestamp>.tar.gzДля переноса сервера или отката данных:
bash
ush platform restore unishift-backup-*.tar.gz --yesПодробно о флагах и составе архива — в документации CLI, а пошаговый перенос описан в SERVER_MIGRATION.md.
Самодиагностика стека (doctor)
Самые частые причины сбоя ush platform install — неработающий Docker daemon, конфликты портов с уже запущенными сервисами на сервере, повреждённый .env с пустыми секретами или сбои инициализации базы данных.
Инструмент самодиагностики проверяет все эти точки:
bash
ush platform doctorЧто проверяется:
- Docker: бинарник
docker, плагинdocker compose v2и права/доступ к демону. - Хостовые порты: проверяет все 28 стандартных портов платформы — по одной переменной на сервис в
.env(включаяNATS_MONITOR_PORTиMINIO_CONSOLE_PORT;DATA_TABLES_PORTзарезервирован). Если порт уже занят сторонним процессом (nginx, системный postgres и т.д.), команда выведет точное имя порта и переменной. Если порт занят контейнером текущего стека Unishift — статус помечается как валидный (PASS). - Секреты: при наличии
.envпроверяется непустота всех 8 обязательных сгенерированных секретов (DB_PASSWORD,JWT_SECRET,SESSION_SECRET,ENCRYPTION_KEY,SERVICE_TOKEN,CENTRIFUGO_API_KEY,SEARXNG_SECRET,MINIO_ROOT_PASSWORD) и фиксируется дрифт остальных ключей. - БД и контейнеры: проверяется
health-статусpostgresиminio, а также отсутствие упавших/завершившихся с ошибкой сервисов.
ush platform install выполняет проверку Docker и портов автоматически в режиме preflight перед началом скачивания образов и конфигов.
Локальные модели
Prod-стек не содержит Ollama и llama.cpp. Адрес и имя модели задаёт только провайдер: Настройки → AI Router → Провайдеры моделей (/settings/ai-router/providers).
Готовые GGUF: storage.unishift.ru/models.
| Файл | Имя модели | Capability |
|---|---|---|
littlelamb-planner.gguf | littlelamb-planner | planner |
littlelamb-diagram.gguf | littlelamb-diagram | diagram |
littlelamb-fill.gguf | littlelamb-fill | fill |
littlelamb.gguf | — | исходный чекпоинт, в runtime не импортируется |
Скачайте файл на машину, где уже запущена Ollama, и импортируйте его там. Платформа этот процесс не поднимает.
bash
curl -fL -o littlelamb-planner.gguf \
https://storage.unishift.ru/models/littlelamb-planner.gguf
printf 'FROM %s\n' "$PWD/littlelamb-planner.gguf" > Modelfile
ollama create littlelamb-planner -f Modelfile
ollama listТо же для littlelamb-diagram.gguf и littlelamb-fill.gguf: имя модели совпадает с именем файла без .gguf.
Провайдер на каждую capability: vendor ollama, ключ пустой, base URL — адрес этой Ollama (нативный API, без суффикса /v1), поле модели — имя из ollama list. Чат — отдельная запись с capability chat и тем же base URL.
Если base URL в приватной сети, для vendor ollama это допустимо. Для vendor openai на тот же адрес нужен ALLOW_PRIVATE_PROVIDER_URLS=true (в prod-compose уже включено) и base URL с суффиксом /v1.
Decision в этом каталоге нет. Если readout нужен, llama.cpp запускается отдельно от стека. Провайдер: capability decision, vendor llamacpp, base URL этого сервера, ключ пустой. Если в GGUF decision-токены помечены как CONTROL, перед запуском их патчит runtime/models/patch_gguf.py: меняются только метаданные 256 токенов, веса не трогаются, повторный запуск безопасен.
Уже установленный стек без ush
На инсталляциях, где в /opt/unishift лежат update.sh / migrate.sh:
bash
curl -fsSL https://storage.unishift.ru/cli/install.sh | bash
ush platform update --public-host <IP>Старые скрипты в каталоге можно удалить — CLI их не вызывает.
Обновление
bash
ush platform updateКоманда скачивает актуальные docker-compose.yaml и конфиги, накатывает миграции и делает docker compose up -d. Образы сервисов помечены тегом latest и pull_policy: always — up подтягивает свежую сборку. Инфраструктура (postgres, nats, minio, centrifugo) закреплена на конкретных версиях и не перекачивается.
Закрепить версию
Чтобы зафиксировать конкретную версию сервисов вместо latest, задайте TAG в .env и перезапустите:
env
TAG=0.0.3bash
ush platform upМиграции
Установщик накатывает их автоматически. Запустить вручную (например, после обновления образов с новыми миграциями):
bash
ush platform migrateКоманда поднимает postgres и minio, создаёт бакет и по очереди прогоняет миграции 19 сервисов с БД (auth, spaces, documents, command-manager, scheduler, storage, env-manager, flow-manager, spark-grid, ai-router, task-tracker, notifications, mcp-gateway, messaging, collatio, concierge, guard, notebooks, proxy-manager). Каждый прогон идёт через одноразовый контейнер и убирается за собой.
Переустановка с нуля
Тома с данными переживают down. Чтобы удалить и данные тоже:
bash
ush platform down --volumes # СНОСИТ тома: БД, файлы MinIO, данные NATSПосле этого при следующем up PostgreSQL заново отработает init-скрипты и создаст пустые базы — понадобится повторный ush platform migrate.
Если миграции падают с postgres is unhealthy
Сначала выполните самодиагностику:
bash
ush platform doctorКоманда покажет текущий статус здоровья postgres и minio и зафиксирует упавшие сервисы.
Permission denied на /docker-entrypoint-initdb.d
В логах postgres:
text
ls: cannot open directory '/docker-entrypoint-initdb.d/': Permission deniedи статус Restarting (2). На VPS с umask 077 каталог postgres/init создаётся как 700 root:root, а процесс внутри контейнера идёт под uid 999 и не может его прочитать.
bash
chmod -R a+rX /opt/unishift/postgres /opt/unishift/centrifugo /opt/unishift/searxng
ush platform down --volumes
ush platform migrate
ush platform upHealthcheck не успевает при первом старте
Postgres при холодном старте создаёт десяток баз (init-скрипты). Если healthcheck слишком короткий, контейнер помечается unhealthy, и *-migrate падают с dependency failed to start.
Диагностика:
bash
ush platform ps
ush platform logs --tail 80 postgres
docker inspect "$(cd /opt/unishift && docker compose ps -q postgres)" --format '{{json .State.Health}}'Восстановление (.env с секретами сохраняется, сносятся только тома):
bash
ush platform down --volumes
ush platform update