Deployment
Simmetric Chat - air-gap capable и local-first. Пять целей развёртывания: Docker Compose multi-container (рекомендуется для продакшена), единый all-in-one container (air-gapped окружения), управляемый стек Coolify, dev override (hot-reload на Docker) и d…
Simmetric Chat - air-gap capable и local-first. Пять целей развёртывания: Docker Compose multi-container (рекомендуется для продакшена), единый all-in-one container (air-gapped окружения), управляемый стек Coolify, dev override (hot-reload на Docker) и desktop Tauri. Все артефакты живут в docker/; desktop shell в src-tauri/. Опубликованные на GHCR образы только amd64 (linux/amd64 - эмулированные через QEMU arm64-сборки зависали; на arm64 делается локальный self-build с нативного хоста). Все контейнеры используют wget healthcheck (--spider): server GET /api/health, collector GET /api/health на 3210, widget GET /health на 3211, Postgres pg_isready, Redis redis-cli ping.
Предварительные требования
- Node.js ≥ 24, pnpm 11.24.0, PostgreSQL 16.
- Для локального embedding: ~2 GB RAM на
all-MiniLM-L6-v2(Xenova, CPU). - Для локального LLM: Ollama с предварительно загруженной моделью(ями) (
gemma4:latestпо умолчанию). - Для vision OCR: Ollama с vision-моделью (
glm-ocr:latestпо умолчанию).
Docker Compose (продакшен)
Продакшен-compose (docker/docker-compose.yml) определяет 6 активных сервисов: frontend (nginx, :80/:443), server (:3000), collector (:3210), widget (:3211), postgres (16, образ pgvector/pgvector:pg16), redis (7-alpine, опциональный кэш масштабирования). ollama и qdrant отключены по умолчанию (закомментированные блоки: раскомментируй + задай OLLAMA_BASE_URL / VECTOR_DB_PROVIDER=qdrant для их использования).
cp .env.example .env
# Отредактируй .env: JWT_SECRET, COLLECTOR_SECRET, WIDGET_API_KEY, DATABASE_URL, LICENSE_KEY (если Enterprise)
docker compose -f docker/docker-compose.yml up -dКритичные продакшен-env (см. 03 - Configuration):
JWT_SECRET- обязателен, криптографический материал (выводитENCRYPTION_KEYпри unset).COLLECTOR_SECRET- обязателен, должен совпадать между server и collector.WIDGET_API_KEY- обязателен для виджета, должен совпадать между widget и server.DATABASE_URL- PostgreSQL 16.LICENSE_KEY+LICENSE_SECRET- только Enterprise.ENCRYPTION_KEY(base64 32 байта) - рекомендован для постоянного data-at-rest за пределами ротацийJWT_SECRET.
Ротация ключей: задай LEGACY_PREVIOUS_ENCRYPTION_KEYS (CSV base64 32-byte) для сохранения расшифровываемости старых бэкапов/данных во время ротации. Автоматического job re-encryption не существует: ручная процедура decrypt-old → re-encrypt-new.Авто-provisioning ключей (entrypoint server)
Продакшен entrypoint (docker/entrypoint-server.sh) при каждом boot выполняет: provisioning ENCRYPTION_KEY и API_KEY_HMAC_SECRET с приоритетом значение оператора > значение, сохранённое в volume server-storage > сгенерировано один раз и сохранено (никогда не перегенерируется на существующем материале); затем prisma migrate deploy + seed и запуск сервера. Dev-конфигурации (docker-compose.dev.yml) пропускают provisioning и сохраняют scrypt fallback.
Volumes и персистентность
- PostgreSQL: выделенный volume (
pgdata). - LanceDB:
${STORAGE_PATH}/vectors/lancedb(collector). - File storage:
${STORAGE_PATH}(collector, документы/аватары/загрузки). - Backup: назначения, настроенные per-job (disk/S3/Dropbox/...).
Health check после deploy
Контейнеры само-верифицируются через wget (см. интро). Эквивалентные ручные проверки:
curl http://localhost:3000/api/health
# { "status": "ok", "checks": { "database": "ok", "collector": "ok", "disk": "ok" } }
curl http://localhost:3210/api/health # collector
curl http://localhost:3211/health # widgetЕдиный all-in-one container
docker/Dockerfile собирает единый образ, управляемый supervisord, который запускает PostgreSQL 16 (pgvector скомпилирован offline для air-gap), server, collector и widget. Экспонирует 3000/3210/3211, использует DATABASE_URL на localhost, healthcheck на /api/health. Рассчитан на air-gapped/offline/demo окружения: env по умолчанию - placeholder'ы, переопредели их через .env или -e.
Coolify
docker/docker-compose.coolify.yml + docker/nginx.coolify.conf автоматизируют сборку образов, внутренний networking, volumes, healthchecks и mount enterprise-плагина (абсолютный host-путь ${ENTERPRISE_PLUGIN_PATH:-/opt/simmetric-enterprise}). Требуемые секреты используют синтаксис :? (Coolify отказывает в deploy при их отсутствии): JWT_SECRET, COLLECTOR_SECRET, WIDGET_API_KEY, POSTGRES_PASSWORD, APP_URL, ALLOWED_ORIGINS. Отличия от базового compose: нет container_name, нет host-порта у приложений (ingress доверен Traefik, HTTP-only - TLS терминируется Traefik), ENCRYPTION_KEY/API_KEY_HMAC_SECRET не интерполируются (авто-provisioning в volume).
Локальная разработка
pnpm install
pnpm db:generate # Prisma client (+ fix symlink Prisma/pnpm)
pnpm --filter server db:migrate # применяет миграции
pnpm dev # turborepo: server + collector + widget + frontend параллельноДетали в 10 - Development.
Dev override (Docker)
docker/docker-compose.dev.yml монтирует исходники на продакшен-compose для hot-reload (NODE_ENV=development). docker-compose.infra.yml запускает только Postgres/Qdrant, приложение работает на хосте.
Desktop (Tauri)
src-tauri/ - desktop-приложение, оборачивающее фронтенд. Сборка через pnpm tauri build. Настрой src-tauri/tauri.conf.json для удалённого server URL или локального bundle.
Reverse proxy (Nginx)
Ключевые моменты:
- SSE: отключить buffering (
proxy_buffering off;,X-Accel-Buffering: noуже отправляется server/widget). - Timeout: медленные локальные LLM → высокий
proxy_read_timeout(≥ 600s, дефолтный agent watchdog - 10 min). - Upload:
client_max_body_size≥ 100 MB (лимит multer документов). - CORS: allowlist управляется на стороне приложения (
ALLOWED_ORIGINS); у виджета динамический per-origin CORS (allowedOrigins).
Backup в продакшене
- Создай назначение (
POST /api/backup-destinations). - Создай job (
POST /api/backup-jobs) с cronfrequency/time+retentionDays. - Проверь через
POST /backup-destinations/:id/testи ручной runPOST /backup-jobs/:id/run. - Restore:
POST /api/backups/restore/:logId(dry-run рекомендуется заранее:/restore/:logId/dry-run). Атомарность через psql--single-transaction.
См. 05 - Feature Guide § Backup.
Продакшен-безопасность
- Смени bootstrap-пароль админа; задай
ALLOW_REGISTRATION=falseв prod (самостоятельная регистрация закрыта). DLP_ENABLEDпо умолчанию"true"в v0.22 - redaction input/output чата по 10 встроенным паттернам (см. 05 - Feature Guide); используйDLP_BYPASS_ROLESдля освобождения выбранных ролей.- Включи
audit_log_immutable(Enterprise) для append-only аудита. - HTTPS терминируется на reverse proxy; header'ы
helmetактивны на server (ослаблены на widget для embedding). - Rate limit уже настроены (см. 04 - API Reference § Rate limit): лимит чата теперь управляется budget tracker агента (per-user конкурентность, wallclock, token) плюс глобальная защитная сеть 200 req/min.
Cross-link
- Полные env: 03 - Configuration
- Разработка: 10 - Development
- Deploy troubleshooting: 12 - Troubleshooting