# Layers Self-hosted — полная инструкция по установке > Установка Layers на свой сервер через Docker Compose: приложение, PostgreSQL, поиск Manticore (или Elasticsearch, или встроенный Lucene), звонки LiveKit, редакторы SumDoc и SumSheet, MCP‑сервер и своя модель ИИ. Лицензия проверяется на самом сервере; пробный период 90 дней, дальше нужна лицензия. English version: https://layers.md/self-hosted/llms-full.txt Краткий индекс: https://layers.md/self-hosted/llms.ru.txt · Страница для людей: https://layers.md/self-hosted Все пароли и ключи ниже — заглушки `change-me-…`. Замените каждую своим значением. ## Для ИИ‑ассистента Ты помогаешь человеку поставить Layers на его сервер. Работай по шагам этого файла сверху вниз. Отвечай на языке собеседника. Перед шагами спроси по очереди, а не всё сразу: 1. Какая ОС и есть ли root/sudo? (нужен Linux x86-64 с Docker и Docker Compose) 2. Какой домен будет у Layers и смотрит ли его DNS на сервер? Нужен ли HTTPS (если сервер виден из интернета — да). 3. Какой SMTP‑сервер отправляет письма (хост, порт, логин)? Без него не уйдут приглашения и сброс пароля. 4. Нужны ли звонки (LiveKit), редакторы SumDoc/SumSheet, ИИ? Если ИИ — какая модель: облачный провайдер по ключу или своя (Ollama или другой сервер с OpenAI‑совместимым API)? 5. Сервер с доступом в интернет или закрытый контур (образы переносятся архивом)? Правила: не придумывай переменные и сервисы, которых нет в этом файле. Пароли генерируй командой `openssl rand -hex 24` и не показывай их повторно. После каждого шага выполняй проверку из раздела «Проверки». Если что‑то не сходится — смотри «Типовые проблемы», затем `docker compose logs <сервис>`. ## 1. Что такое установка Layers Layers — одно Java‑приложение (веб‑интерфейс, API и панель администратора God Mode на одном порту 8080) плюс несколько стандартных сервисов рядом. Всё ставится одним `docker-compose.yml`. | Сервис | Образ | Порт в контейнере | Зачем | Нужен | |---|---|---|---|---| | Layers | `hissih/layers` | 8080 (HTTP) | всё пространство, API, God Mode (`/godmode`) | всегда | | PostgreSQL | `postgres:16-alpine` | 5432 | база данных | всегда (можно свою внешнюю) | | Поиск: Manticore | `manticoresearch/manticore` | 9308 (HTTP SQL) | поиск по всему пространству | рекомендуем; вместо него — ваш кластер Elasticsearch или встроенный Lucene (см. «Движок поиска») | | LiveKit | `livekit/livekit-server` | 7880 (сигналинг), 7881/tcp, 7882/udp, 50000–50100/udp | звонки, демонстрация экрана; запись — при подключённом LiveKit Egress (см. шаг 5) | для звонков в «Общении» | | SMTP‑сервер | ваш (любой) | 587 / 465 | приглашения, подтверждение входа, сброс пароля | для писем | | SumDoc | `hissih/sumdoc-webhost` | 8090 | редактор документов .docx в браузере | для документов | | SumSheet | `hissih/sumsheet-webhost` | 8092 | редактор таблиц .xlsx/.xlsm в браузере | для таблиц | | MCP‑сервер | `sinups/layers-mcp-server` | 8091 (`/mcp`) | ИИ‑помощник и внешние агенты (Claude, Cursor) работают с задачами и страницами | по желанию | | LLM | ваш провайдер | — | ИИ: помощник, сводки, ответы | по желанию | Что будет без необязательного сервиса: - **без LiveKit** — нет звонков; чаты работают; - **без SumDoc / SumSheet** — .docx и .xlsx на Диске открываются в OnlyOffice, если он установлен из каталога модулей, иначе карточкой файла со скачиванием; - **без SMTP** — не уходят приглашения, подтверждение регистрации и сброс пароля; - **без LLM** — нет ИИ‑функций; всё остальное работает; - **без MCP‑сервера** — помощник не выполняет действия в пространстве, внешние агенты не подключаются; - **без Manticore** — используйте свой кластер Elasticsearch или встроенный Lucene (см. «Движок поиска»); если Manticore временно недоступен, Layers сам переключается на Lucene. ### Требования - Linux **x86-64** (образы Layers и редакторов собраны под `linux/amd64`, arm64‑образов нет), Docker и Docker Compose. - PostgreSQL (в compose ниже — `postgres:16-alpine`; можно свою внешнюю базу). - Редакторы SumDoc / SumSheet: каждый открытый документ — свой процесс, браузер подключается к нему по WebSocket. Сколько документов открыто одновременно, ограничивает `--max-cabins`; если памяти узла на них не хватает, `/health` редактора пишет предупреждение в `warnings`. - Файл до 900 МБ по умолчанию (меняется переменной, см. ниже). Место на диске зависит от ваших файлов: они лежат в томе `layers_data` (или в S3). ## 2. Установка ### Шаг 1. Подготовьте сервер ```bash docker --version docker compose version mkdir -p /opt/layers && cd /opt/layers # пароли — по одному на каждую заглушку change-me openssl rand -hex 24 ``` Нужен домен, который смотрит на сервер (например, `example.com`). Без домена можно работать по `http://IP:8080` внутри сети — тогда во всех переменных ниже вместо `https://example.com` укажите этот адрес. ### Шаг 2. Создайте `docker-compose.yml` Сохраните в `/opt/layers/docker-compose.yml`. Замените `example.com` на свой домен и все `change-me-…` на свои значения. Необязательные сервисы (звонки, редакторы, MCP) можно удалить вместе с их переменными у `layers`. ```yaml name: layers services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: layers POSTGRES_USER: layers POSTGRES_PASSWORD: change-me-db volumes: - pg_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U layers -d layers"] interval: 5s retries: 20 manticore: image: manticoresearch/manticore:latest restart: unless-stopped volumes: - manticore_data:/var/lib/manticore layers: image: hissih/layers:latest platform: linux/amd64 restart: unless-stopped depends_on: db: { condition: service_healthy } manticore: { condition: service_started } ports: - "127.0.0.1:8080:8080" volumes: - layers_data:/root/layers_data environment: SPRING_PROFILES_ACTIVE: server # База DB_SERVER_URL: jdbc:postgresql://db:5432/layers DB_SERVER_USERNAME: layers DB_SERVER_PASSWORD: change-me-db # Панель администратора /godmode ADMIN_USERNAME: admin ADMIN_PASSWORD: change-me-admin # Домен LAYERS_DOMAIN: example.com LAYERS_APP_DOMAIN: example.com APP_REDIRECT_URL: https://example.com APP_CORS_ALLOWED_ORIGINS: https://example.com # Поиск SEARCH_PROVIDER: manticore SEARCH_MANTICORE_ENABLED: "true" SEARCH_MANTICORE_URL: http://manticore:9308 SEARCH_ELASTICSEARCH_ENABLED: "false" # Звонки LIVEKIT_ENABLED: "true" LIVEKIT_URL: ws://livekit:7880 LIVEKIT_PUBLIC_URL: wss://example.com/livekit/ LIVEKIT_API_KEY: change-me-livekit-key LIVEKIT_API_SECRET: change-me-livekit-secret-min-32-characters # Почта (отправка писем) MAIL_PROVIDER: smtp SPRING_MAIL_HOST: smtp.example.com SPRING_MAIL_PORT: "587" SPRING_MAIL_USERNAME: noreply@example.com SPRING_MAIL_PASSWORD: change-me-smtp SPRING_MAIL_SMTP_AUTH: "true" SPRING_MAIL_SMTP_STARTTLS_ENABLE: "true" # Редакторы SumDoc и SumSheet (адреса, которые видит браузер) LAYERS_FASTDOC_URL: https://example.com/sumdoc LAYERS_FASTSHEET_URL: https://example.com/sumsheet # ИИ: модель подключается в God Mode → ИИ AI_ENABLED: "true" ASSISTANT_MCP_URL: http://mcp:8091/mcp AI_USER_MODEL_CHOICE: "true" livekit: image: livekit/livekit-server:latest restart: unless-stopped environment: LIVEKIT_CONFIG: | port: 7880 bind_addresses: [""] rtc: tcp_port: 7881 port_range_start: 50000 port_range_end: 50100 use_external_ip: true keys: change-me-livekit-key: change-me-livekit-secret-min-32-characters webhook: api_key: change-me-livekit-key urls: - http://layers:8080/v1/livekit/webhook ports: - "7880:7880" - "7881:7881" - "7882:7882/udp" - "50000-50100:50000-50100/udp" sumdoc: image: hissih/sumdoc-webhost:latest platform: linux/amd64 restart: unless-stopped command: ["--base-path", "/sumdoc", "--max-cabins", "12", "--idle-min", "20", "--auth-url", "http://layers:8080/v1/me", "--attach-url", "http://layers:8080/v1/attachments/{id}/content"] ports: - "127.0.0.1:8090:8090" volumes: - sumdoc_cabins:/data/cabins sumsheet: image: hissih/sumsheet-webhost:latest platform: linux/amd64 restart: unless-stopped command: ["--base-path", "/sumsheet", "--max-cabins", "12", "--idle-min", "20", "--auth-url", "http://layers:8080/v1/me", "--attach-url", "http://layers:8080/v1/attachments/{id}/content"] ports: - "127.0.0.1:8092:8092" volumes: - sumsheet_cabins:/data/cabins mcp: image: sinups/layers-mcp-server:latest # тот же образ ставит каталог модулей God Mode restart: unless-stopped depends_on: [layers] environment: SPRING_PROFILES_ACTIVE: server SERVER_PORT: "8091" LAYERS_BACKEND_BASEURL: http://layers:8080 LAYERS_BACKEND_FORWARDINCOMINGAUTH: "true" LAYERS_BACKEND_REQUIREINCOMINGAUTH: "true" ports: - "127.0.0.1:8091:8091" volumes: pg_data: manticore_data: layers_data: sumdoc_cabins: sumsheet_cabins: ``` Важно: - Том Layers монтируется именно в `/root/layers_data`. Там лежат файлы, настройки God Mode (`application-external.properties`), секреты JWT и шаблоны писем. Другой путь — и настройки теряются при обновлении. - `POSTGRES_PASSWORD` и `DB_SERVER_PASSWORD` должны совпадать. PostgreSQL берёт пароль только при создании тома. - Ключ и секрет LiveKit должны совпадать в `LIVEKIT_CONFIG` и у `layers`. Секрет — не короче 32 символов. - Порт 8080 открыт только на `127.0.0.1`: снаружи Layers доступен через nginx (шаг 4). ### Движок поиска: Manticore, Elasticsearch или Lucene В Layers три движка поиска; выбор — переменная `SEARCH_PROVIDER` (`search.provider`): `auto`, `manticore`, `elasticsearch` или `lucene`. - **Manticore** — рекомендуем: отдельный лёгкий контейнер, он уже в compose выше. - **Elasticsearch** — если в компании уже есть кластер. Удалите сервис `manticore` и его `depends_on`, а у `layers` задайте: ```yaml SEARCH_PROVIDER: elasticsearch SEARCH_ELASTICSEARCH_ENABLED: "true" SEARCH_MANTICORE_ENABLED: "false" ES_HOST: elasticsearch.example.com ES_PORT: "9200" ES_PROTOCOL: https # по умолчанию http ES_USERNAME: layers ES_PASSWORD: change-me-es ``` - **Lucene** — встроенный, без отдельного сервиса. Индекс лежит в каталоге файлов Layers (`<хранилище файлов>/lucene_index_v5`, то есть в томе `layers_data`). Подходит для небольшой установки: ```yaml SEARCH_PROVIDER: lucene SEARCH_MANTICORE_ENABLED: "false" SEARCH_ELASTICSEARCH_ENABLED: "false" ``` После смены движка — полная переиндексация: God Mode → Платформа → Поиск. ### Шаг 3. Запустите ```bash cd /opt/layers docker compose up -d docker compose logs -f layers # ждите строку «Started LayersApplication» (15–60 с) curl -s http://127.0.0.1:8080/health # OK ``` Откройте `https://example.com` (или `http://IP:8080`) — создайте первый аккаунт. Панель администратора: `https://example.com/godmode/login`, логин `admin` и `ADMIN_PASSWORD`. ### Шаг 4. HTTPS через nginx Layers отдаёт всё сам с порта 8080 — отдельный веб‑сервер нужен только чтобы завершать TLS. В локальной сети или за корпоративным прокси nginx не обязателен: направьте прокси на порт 8080. ```bash sudo apt install nginx certbot python3-certbot-nginx sudo certbot certonly --nginx -d example.com ``` `/etc/nginx/sites-available/layers.conf`: ```nginx server { listen 80; server_name example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://example.com$request_uri; } } server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; client_max_body_size 1000m; add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; # Layers: веб, API, God Mode location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 300; } # LiveKit: сигналинг по WebSocket (слеш в конце proxy_pass обязателен) location /livekit/ { proxy_pass http://127.0.0.1:7880/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400s; } # LiveKit REST: SDK сервера ходит в /twirp/ от корня location /twirp/ { proxy_pass http://127.0.0.1:7880/twirp/; proxy_set_header Host $host; proxy_read_timeout 86400s; } # Редакторы: тот же домен, чтобы редактор получил cookie входа Layers location /sumdoc { proxy_pass http://127.0.0.1:8090; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } location /sumsheet { proxy_pass http://127.0.0.1:8092; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; } # MCP для внешних агентов (необязательно) location /mcp { proxy_pass http://127.0.0.1:8091/mcp; proxy_http_version 1.1; proxy_set_header Host $host; proxy_buffering off; proxy_read_timeout 3600s; } } ``` ```bash sudo ln -s /etc/nginx/sites-available/layers.conf /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t && sudo systemctl reload nginx sudo certbot renew --dry-run ``` Не добавляйте `limit_req` (интерфейс грузит десятки файлов на страницу, защита от перебора паролей встроена) и не отдавайте статику из nginx — Layers сам ставит заголовки кэша. ### Шаг 5. Звонки (LiveKit) Откройте медиа‑порты на файрволе сервера: ```bash sudo ufw allow 7881/tcp sudo ufw allow 7882/udp sudo ufw allow 50000:50100/udp ``` В God Mode → **Приложения → Интеграции → LiveKit**: адрес WebSocket `wss://example.com/livekit/` (слеш в конце обязателен), ключ и секрет — как в compose. «Сохранить» → «Проверить подключение» → «Включить». Если в логах LiveKit `could not validate external IP` (исходящий UDP к STUN закрыт хостингом), замените в `LIVEKIT_CONFIG` строку `use_external_ip: true` на `node_ip: <публичный IP сервера>`. В закрытой сети `node_ip` — адрес сервера в этой сети. Запись звонков на своём сервере не ограничена тарифом, но для неё нужен отдельный сервис LiveKit Egress (с Redis — по документации LiveKit); в этом compose его нет. По умолчанию записывается только звук (`LIVEKIT_RECORDING_AUDIO_ONLY`, по умолчанию `true`). Запись включает модератор группы. Диапазон UDP 50000–50100 хватает для обычной нагрузки; при многих одновременных звонках расширьте его в `LIVEKIT_CONFIG` и в `ports` одновременно. ### Шаг 6. Почта Два разных механизма: 1. **Письма от Layers** (приглашения, подтверждение, сброс пароля) — SMTP из шага 2 (`MAIL_PROVIDER: smtp`). Порт 587 — STARTTLS; для 465 вместо STARTTLS задайте `SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE: "true"`. Те же настройки есть в God Mode → **Платформа → Почта**, там же — тестовое письмо и шаблоны писем. Другие провайдеры: `MAIL_PROVIDER: sendgrid` (`SENDGRID_API_KEY`, `SENDGRID_FROM`) или `mailchimp` (`MAILCHIMP_API_KEY`). 2. **Модуль «Почта»** — почтовый клиент внутри Layers. Люди подключают свои существующие ящики по IMAP/SMTP. Свой почтовый сервер Layers не поднимает. ### Шаг 7. Редакторы SumDoc и SumSheet Они уже в compose. Редактор не хранит пользователей и файлы: он спрашивает Layers «кто это» (`/v1/me`, по cookie пользователя) и берёт файл по id (`/v1/attachments/{id}/content`). Поэтому редакторы открываются на том же домене, что и Layers (`/sumdoc`, `/sumsheet` в nginx). Проверка: ```bash curl -s http://127.0.0.1:8090/sumdoc/health # "status": "ok", …, "version": {…, "skewMin": 0} curl -s http://127.0.0.1:8092/sumsheet/health # "status": "ok", …, "version": {…, "skewMin": 0} curl -s https://example.com/v1/capabilities # {"fastdoc":{"enabled":true,"url":"https://example.com/sumdoc"},"fastsheet":{"enabled":true,"url":"https://example.com/sumsheet"},…} ``` `skewMin: 0` (в блоке `version`) значит, что редактор и движок из одного релиза. `--max-cabins` — сколько документов открыто одновременно. Без `LAYERS_FASTDOC_URL` / `LAYERS_FASTSHEET_URL` Диск открывает такие файлы в OnlyOffice, если он установлен из каталога модулей, иначе карточкой со скачиванием. ### Шаг 8. ИИ: своя модель или провайдер Модель подключается в God Mode → **ИИ → Провайдеры → Добавить провайдера**. Типы: OpenAI, OpenRouter, Gonka и **«Своё подключение»** — любой сервер с OpenAI‑совместимым API, например Ollama. Для своего подключения ключ не обязателен. Укажите адрес, нажмите «Проверить» — Layers покажет модели, которые отдаёт сервер; выберите нужные и включите провайдера. Возможности провайдера: чат, инструменты, расшифровка, векторы, рассуждения. Локальная модель через Ollama в том же compose: ```yaml ollama: image: ollama/ollama:latest restart: unless-stopped volumes: - ollama_data:/root/.ollama # и в volumes: # ollama_data: ``` ```bash docker compose up -d ollama docker compose exec ollama ollama pull gpt-oss:20b ``` Адрес в «Своём подключении»: `http://ollama:11434/v1`. Если Ollama или другой сервер с OpenAI‑совместимым API работает на отдельной машине — его адрес с `/v1` на конце, например `http://<адрес>:11434/v1` для Ollama. Модель подбирайте под память сервера с моделью. Переменные ИИ у `layers`: | Переменная | Что делает | |---|---| | `AI_ENABLED` | включает ИИ‑функции | | `ASSISTANT_MCP_URL` | адрес MCP‑сервера, через который помощник выполняет действия в пространстве (`http://mcp:8091/mcp`) | | `AI_USER_MODEL_CHOICE` | люди могут выбирать модель в помощнике | Внешние агенты (Claude, Cursor и другие MCP‑клиенты) подключаются к `https://example.com/mcp` с личным токеном: в Layers → **Настройки → Токены доступа → Добавить токен** (права «Только чтение» или «Чтение и запись», срок действия). ### Шаг 9. Первый вход в God Mode `https://example.com/godmode/login` → `admin` / ваш `ADMIN_PASSWORD`. Раздел **«Начало работы»** — чек‑лист настройки сервера: домены и адреса, почта, вход, модули, брендинг. Отметка «сделано» ставится по фактическому состоянию сервера. Разделы панели: Система (домены и адреса, база данных, SSL, хранилище файлов, перезапуск, доступ в God Mode, лицензия), Платформа (почта, поиск, мониторинг ошибок, аналитика, инфраструктурные сервисы), Продукт (модули, брендинг, правовые документы, аутентификация), ИИ, Приложения (магазин приложений, интеграции), Люди (пользователи, аудит), Эксплуатация (состояние системы, кластер, очередь писем, фичефлаги, квоты). Каталог модулей (God Mode → Приложения → Магазин приложений) ставит модули, скачивая их образы из реестра Docker. Он работает, только если контейнеру Layers дан доступ к Docker (`LAYERS_APPSTORE_DOCKER_ENABLED: "true"` и Docker‑сокет, см. deploy/DOCKER.md); без доступа к реестру установка модулей из каталога недоступна. Способы входа (God Mode → Продукт → Аутентификация или переменные): логин и пароль, Google (`GOOGLE_AUTH_ENABLED`, `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `GOOGLE_REDIRECT_URI`), Яндекс (`YANDEX_AUTH_ENABLED`, …), VK (`VK_AUTH_ENABLED`, …), Госуслуги (`ESIA_AUTH_ENABLED`, …). SAML, LDAP и SCIM не поддерживаются. ### Шаг 10. Лицензия Пробный период — **90 дней**, дальше нужна лицензия. Отсчёт — с самого раннего пространства на сервере. Лицензия проверяется на самом сервере. Без ключа после пробного периода сервер не блокирует вход и данные (`regime` → `quiet`), медленнее идут машинные задачи. Ключ — одна строка. God Mode → **Система → Лицензия → «Вставьте ключ» → «Применить ключ»**. ```bash curl -s https://example.com/layers/license/status # {"mode":"MISSING",…,"node":{"regime":"evaluation","day":2,"evaluationDaysLeft":89,…}} ``` С ключом `regime` становится `full`. Ключ: contacts@layers.md. ### Шаг 11. Обновления ```bash cd /opt/layers docker compose pull docker compose up -d ``` Данные, файлы и настройки God Mode остаются в томах `pg_data` и `layers_data`. Если в новой версии появился новый сервис, `pull` его не добавит — допишите блок сервиса в compose и снова `docker compose up -d`. Для предсказуемых обновлений закрепите тег образа (например, `hissih/layers:2.1.184-unified-20261001-v13`) вместо `latest`. Запущенный тег виден в God Mode → Эксплуатация → Состояние системы. ### Шаг 12. Резервные копии Встроенного бэкапа базы в панели нет — делайте его средствами PostgreSQL и копией тома с файлами. ```bash cd /opt/layers # база docker compose exec -T db sh -c 'pg_dump -U $POSTGRES_USER $POSTGRES_DB' | gzip > layers-db-$(date +%F).sql.gz # файлы, настройки God Mode, секреты JWT docker run --rm -v layers_layers_data:/data -v "$PWD":/backup alpine \ tar czf /backup/layers-data-$(date +%F).tar.gz -C /data . ``` Восстановление базы в пустой том: ```bash gunzip -c layers-db-2026-10-02.sql.gz | docker compose exec -T db sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB' ``` Имя тома — `<имя проекта>_layers_data`; с `name: layers` в compose это `layers_layers_data` (проверьте: `docker volume ls`). ### Закрытый контур Скачайте образы на машине с интернетом и перенесите архивом: ```bash IMAGES="hissih/layers:latest postgres:16-alpine manticoresearch/manticore:latest livekit/livekit-server:latest \ hissih/sumdoc-webhost:latest hissih/sumsheet-webhost:latest sinups/layers-mcp-server:latest" for i in $IMAGES; do docker pull "$i"; done docker save $IMAGES | gzip > layers-images.tar.gz # на сервере в закрытой сети gunzip -c layers-images.tar.gz | docker load docker compose up -d ``` Что работает в закрытой сети: - лицензия проверяется на самом сервере; - LiveKit — с `node_ip` = адрес сервера в этой сети (шаг 5); - ИИ — только своя модель в этой сети: Ollama или другой сервер с OpenAI‑совместимым API (шаг 8). Каталог модулей без доступа к реестру Docker недоступен: модули из него не установятся. Вход через Google, Яндекс, VK и Госуслуги, а также Unsplash и GIPHY требуют доступа к этим сервисам. ## 3. Полезные переменные | Переменная | По умолчанию | Что делает | |---|---|---| | `APP_JWT_SECRET` | создаётся сам и хранится в `layers_data` | секрет сессий; задавайте явно только при необходимости (`openssl rand -hex 64`) | | `FILE_STORAGE_TYPE` | `LOCAL` | `S3` — файлы в S3‑совместимом хранилище (`USE_AWS`, `S3_BUCKET_NAME`, `S3_REGION`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`); также God Mode → Система → Хранилище файлов | | `SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE`, `SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE` | 900MB | предел размера файла; nginx `client_max_body_size` должен быть не меньше | | `FRONTEND_APP_NAME`, `FRONTEND_LOGO_FULL_URL`, `FRONTEND_LOGO_ICON_URL` | — | название и логотип (также God Mode → Продукт → Брендинг) | | `USE_SENTRY`, `SENTRY_DSN` | выключено | отправка ошибок сервера в ваш Sentry | | `UNSPLASH_ENABLED` / `GIPHY_ENABLED` | выключено | поиск картинок и GIF (нужны ключи и интернет) | | `REINDEX_ON_STARTUP` | `false` | полная переиндексация поиска при старте | Всё, что задаётся переменными, можно менять и в God Mode. Переменные применяются при старте и перекрывают значения из панели. ## 4. Проверки после установки ```bash docker compose ps # все сервисы Up, db — healthy curl -s https://example.com/health # OK curl -s https://example.com/layers/license/status # "regime":"evaluation" или "full" curl -s https://example.com/v1/capabilities # fastdoc / fastsheet: "enabled": true curl -s http://127.0.0.1:8090/sumdoc/health # "status": "ok" curl -s http://127.0.0.1:8092/sumsheet/health # "status": "ok" curl -s http://127.0.0.1:8091/actuator/health # MCP: "status":"UP" ``` В интерфейсе: 1. God Mode → «Начало работы»: все пункты «сделано». 2. Платформа → Почта: тестовое письмо пришло. 3. Интеграции → LiveKit: «Проверить подключение» → зелёное уведомление; звонок между двумя браузерами идёт. 4. На Диске .docx открывается в SumDoc, .xlsx — в SumSheet. 5. ИИ → провайдер «Проверено», модели выбраны; помощник отвечает. ## 5. Типовые проблемы | Симптом | Причина и решение | |---|---| | `password authentication failed` | пароль PostgreSQL сменили после создания тома. Сохранить данные: `docker compose exec db psql -U layers -d layers -c "ALTER USER layers PASSWORD 'новый'"`; или пересоздать: `docker compose down -v` (удалит данные) | | Сервер не стартует: `workspaces_plan_check` | `docker compose exec db psql -U layers -d layers -c "ALTER TABLE workspaces DROP CONSTRAINT IF EXISTS workspaces_plan_check;"` и `docker compose restart layers` | | 502/503 после обновления | приложению нужно 15–60 с на старт; `docker compose logs layers --tail=20`, ждите «Started LayersApplication» | | Ошибки CORS в браузере | `APP_CORS_ALLOWED_ORIGINS` должен точно совпадать с адресом в браузере (схема и порт) | | Загрузка файла: `ERR_NOT_MULTIPART` или 413 | увеличьте `client_max_body_size` в nginx и при необходимости `SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE` | | После перезапуска всех разлогинило | потерян том `layers_data` (там секрет JWT) или он смонтирован не в `/root/layers_data` | | Звонок соединяется, но нет звука и видео | закрыты UDP 50000–50100 или 7882; `could not validate external IP` — задайте `node_ip` | | God Mode: LiveKit «недоступен», HTTP 401 при верных ключах | нет `location /twirp/` в nginx; проверьте `GET /v1/livekit/status` | | `baseUrl must end in /` | адрес LiveKit в God Mode без слеша в конце: нужен `wss://example.com/livekit/` | | Документ открывается карточкой со «Скачать» или в OnlyOffice | не заданы `LAYERS_FASTDOC_URL` / `LAYERS_FASTSHEET_URL` или редактор не запущен — смотрите `/v1/capabilities` | | Редактор показывает ошибку входа | редактор открыт не на домене Layers (нет cookie) или `--auth-url` не достаёт до `layers:8080` | | Поиск ничего не находит после смены движка | переиндексация из God Mode → Платформа → Поиск | | Модель не видна в «Своём подключении» | адрес должен заканчиваться на `/v1` и быть доступен из контейнера `layers` (не `localhost`, а имя сервиса или IP) | ## 6. Где что лежит | Данные | Где | |---|---| | база | том `pg_data` | | файлы, настройки God Mode, секреты, шаблоны писем | том `layers_data` → `/root/layers_data` | | индекс поиска | том `manticore_data`; с Lucene — внутри `layers_data`; с Elasticsearch — в вашем кластере (всё пересобирается переиндексацией) | | временные копии открытых документов редакторов | тома `sumdoc_cabins`, `sumsheet_cabins` | Вопросы и ключ лицензии: contacts@layers.md