Document how to run a local Hugging Face TEI embeddings server for the AI agent's RAG search, in both README.md and README.ru.md: - Option A: local container on the same Docker network (no auth) - Option B: separate host exposed via Traefik + Let's Encrypt (API key, rate limit, external curl check) - settings tables (Workspace settings -> AI -> Embeddings) and notes on vector dimension (384), weight caching, version pinning, offline, GPU
30 KiB
Gitmost
Совместная вики и система документации с открытым исходным кодом.
Полностью открытый community-форк Docmost.
English · Русский
Об этом форке
Gitmost — это community-форк Docmost, открытой системы для совместной работы над вики и документацией.
Цель форка — сборка на 100% открытая, только под AGPL, без кода Enterprise-редакции (EE):
- Никакого EE-кода. Весь проприетарный код Enterprise-редакции удалён — приватный
сабмодуль
apps/server/src/ee, каталогapps/client/src/ee(201 файл) и пакетpackages/ee. Никаких лицензионных ограничений: все функции доступны всем. - Замены написаны с нуля. Функции, которые раньше были скрыты за enterprise-лицензией
(например, резолв комментариев, чат с AI-агентом, сервер
/mcp), переписаны с нуля поверх community-кодовой базы. EE-код не переиспользуется, нет проверок entitlement и feature-флагов. - Никакого навязывания. В интерфейсе нигде нет плашек «купите лицензию» / «перейдите на Enterprise», напоминаний о триале и заглушек на месте заблокированных функций.
- Аутентификация — обычная пара email + пароль (без SSO/LDAP/облака/биллинга).
Чем отличается от Docmost
| Изменение | Подробности |
|---|---|
| Удалён EE-код | Вырезан весь код Enterprise-редакции на клиенте и сервере; это чистая community/AGPL-сборка без лицензионных проверок. |
| Резолв комментариев | Переписан с нуля как community-функция (резолв / переоткрытие с вкладками «Открытые» / «Решённые»). EE-код не используется, доступно любому, кто может комментировать. |
| Встроенный MCP-сервер | Community MCP-сервер (@docmost/mcp, 40 инструментов) отдаётся по HTTP на /mcp — без enterprise-лицензии. Заменяет удалённый лицензируемый EE MCP. |
| Чат с AI-агентом | Встроенный чат с AI-агентом по содержимому вики, написанный с нуля как community-функция — без enterprise-лицензии. Агент читает и редактирует страницы от вашего имени (в рамках ваших прав), с полнотекстовым + векторным (RAG) поиском и опциональным доступом в интернет через внешние MCP-серверы. |
| Ребрендинг | Логотип / название приложения изменены с Docmost на Gitmost. |
| Компактное дерево страниц | Отступ дерева страниц по умолчанию уменьшен с 16px до 8px на уровень вложенности. |
| Сохранение состояния дерева страниц | Дерево страниц в сайдбаре запоминает, какие узлы вы раскрыли/свернули, между перезагрузками — состояние хранится в браузере (localStorage) отдельно для каждой пары воркспейс + пользователь, чтобы аккаунты в одном браузере не пересекались. В оригинальном Docmost дерево сбрасывается при каждой перезагрузке. |
| CI / образы | Release-CI публикует контейнерные образы в GHCR (ghcr.io/vvzvlad/gitmost) через встроенный GITHUB_TOKEN вместо Docker Hub. |
Встроенный MCP-сервер
В Gitmost есть наш собственный MCP-сервер — docmost-mcp,
который мы написали сами, — встроенный прямо в приложение и доступный на /mcp. Он даёт
40 agent-native инструментов: точечное редактирование по блокам (patch / insert / delete
по id), find/replace с сохранением структуры, скриптовые трансформации (doc) => doc с
предпросмотром диффа, структурное редактирование таблиц, история версий с диффом /
восстановлением, комментарии, изображения и ссылки на шаринг — всё применяется через слой
real-time-коллаборации Docmost, поэтому запись никогда не затирает параллельную правку
человека.
Лучше, чем родной MCP у Docmost. Встроенный MCP у Docmost — enterprise-функция, и его инструменты примитивные: прочитать страницу как Markdown, создать / переместить / удалить страницу, заменить страницу целиком. Наш сделан под то, как агент реально редактирует: адресовать один блок и пропатчить его или запрограммировать изменение, а не гонять документ на ~100 КБ через модель ради каждой мелкой правки. И enterprise-лицензия не нужна.
/mcp в Gitmost (наш docmost-mcp) |
Родной MCP у Docmost | |
|---|---|---|
| Enterprise-лицензия | Не нужна | Нужна |
| Инструменты | 40, agent-native | Примитивные (Markdown, CRUD страниц, замена целиком) |
| Правки по блокам / find-replace / скриптовые трансформации | ✅ | — |
| Структурное редактирование таблиц, дифф / восстановление версий | ✅ | — |
| Комментарии, изображения, ссылки на шаринг | ✅ | — |
| Безопасная запись через real-time-коллаборацию (без затирания) | ✅ | — |
Это тот же сервер, что и отдельный docmost-mcp, — просто встроенный. Это ровно тот самый
docmost-mcp, который можно запускать и отдельно;
от встраивания он не становится «мощнее» — просто не нужно ставить и держать отдельный
процесс. Админ включает его одним переключателем в Настройки воркспейса → AI, а
любой MCP-клиент указывает на ${APP_URL}/mcp.
Чат с AI-агентом
В Gitmost есть встроенный чат с AI-агентом по содержимому вики — написанный с нуля как community-функция, без enterprise-лицензии. Открывается из шапки страницы; агент умеет читать и редактировать ваш воркспейс от вашего имени:
- Полный набор инструментов чтения + записи (~40 штук). Поиск и чтение страниц, точечные правки по блокам и в таблицах, создание / переименование / перемещение страниц, дифф и восстановление версий, создание / резолв комментариев — каждое действие выполняется под вашими правами (Docmost CASL), поэтому агент не видит и не меняет ничего, чего не могли бы вы сами.
- Безопасность по умолчанию. Агенту доступны только обратимые операции (история версий + корзина); перманентное удаление не экспонируется. Правки агента помечаются в истории версий бейджем «AI-агент» со ссылкой на чат.
- Поиск по вашему контенту. Полнотекстовый поиск плюс опциональный векторный (RAG) семантический поиск по страницам.
- Доступ в интернет через внешние MCP. Админ может подключить внешние MCP-серверы (например, Tavily), чтобы дать агенту веб-поиск / доступ в интернет.
- Своя модель. OpenAI-совместимый эндпоинт — OpenAI, OpenRouter, локальный Ollama или любой self-hosted-сервер — плюс модель и API-ключ настраиваются в Настройки воркспейса → AI. Ключ шифруется и никогда не покидает сервер.
Дорожная карта
Готово
- ✅ MCP-сервер — встроенный community MCP-сервер на
/mcp. - ✅ Приложение для macOS — нативное приложение для macOS (gitmost-app), встраивающее UI с вкладками для нескольких серверов.
- ✅ AI-чат — встроенный чат с AI-агентом по содержимому вики (чтение + запись, RAG-поиск, настраиваемый провайдер, опциональный доступ в интернет через внешние MCP).
- ✅ Голосовая диктовка — кнопка-микрофон в чате AI-агента и в редакторе страниц; аудио распознаётся на сервере (Whisper / OpenAI-совместимый STT) через AI-провайдер воркспейса, с тумблером админа для показа/скрытия.
- ✅ Шаблоны страниц — пометить страницу шаблоном и вставлять её содержимое живой ссылкой в другие страницы; правки шаблона распространяются на все места вставки (whole-page-транслюзия поверх существующих synced-блоков).
- ✅ AI-ассистент на публичных шарах — анонимный зритель расшаренной страницы может спросить AI-агента, который ищет строго по дереву этой шары (read-only, share-scoped поиск), за тумблером воркспейса.
- ✅ Сноски — сноски академического вида: нумерованная ссылка-надстрочник прямо в тексте (читается на месте во всплывающем окне по наведению), а текст сноски живёт реальным редактируемым блоком внизу страницы; авто-нумерация, безопасна для совместного редактирования, переживает экспорт/импорт Markdown и доступна AI-агенту / MCP.
- ✅ Временные заметки — создайте временную заметку, и она автоматически уедет в корзину по истечении настраиваемого срока жизни (по умолчанию 24 ч); создать такую можно в один клик с домашнего экрана, с обзора любого пространства или из сайдбара пространства.
В процессе
- 🚧 Синхронизация с Git — двусторонняя синхронизация страниц с Git-репозиторием.
В планах
- 🔭 Комментарии зрителей — возможность комментировать для пользователей с доступом только на чтение.
- 🔭 Защищённые паролем страницы — защита отдельных страниц / шар паролем.
- 🔭 Приложение для Windows / Linux — нативное десктоп-приложение для Windows и Linux.
- 🔭 Мобильное приложение — мобильные приложения (iOS обязательно, Android как пойдёт) на базе существующей адаптивной веб-версии и редактора через обёртку Capacitor; оффлайн запланирован на будущее. См. issue #195.
- 🔭 Офлайн-режим — офлайн-синхронизация и поддержка PWA.
- 🔭 Улучшения редактора и UX — блоки внутри таблиц (списки, чек-листы), колоночная вёрстка, дополнительные уровни заголовков, highlight-блоки, кастомные эмодзи в callout-ах, плавающие изображения, anchor-ссылки на упоминания страниц, тоглы (ширина шары, aside/сайдбар, spellcheck, лигатуры), санитизация экспорта дерева спейса и mentions в хлебных крошках.
С чего начать
Gitmost повторяет процесс установки upstream-Docmost. Инструкции по self-hosting и разработке
смотрите в документации Docmost; где это применимо, заменяйте образ
docmost/docmost на ghcr.io/vvzvlad/gitmost.
Reverse proxy: SSE-стриминговые пути
AI-агент стримит ответы через Server-Sent Events. Эти эндпоинты отдают долгоживущий
text/event-stream-ответ и обязаны обходить буферизацию И сжатие ответов на каждом
прокси перед приложением:
POST /api/ai-chat/stream— живой стрим хода агентаGET /api/ai-chat/runs/<chatId>/stream— подключение/резюм detached-рана (AI_CHAT_RESUMABLE_STREAM)POST /api/shares/ai/stream— анонимный ассистент публичных шар
Буферизующий или сжимающий прокси не ломает эти пути с ошибкой — он тихо их портит:
запрос висит в pending, токены не стримятся и вываливаются одним куском в конце хода,
а перезагруженная вкладка падает в грубый поллинг. Диагностический признак в DevTools —
заголовок Content-Encoding: gzip/zstd на ответе с text/event-stream.
Сервер уже шлёт X-Accel-Buffering: no (nginx учитывает его по умолчанию), но
compression-мидлвари управляются конфигом прокси, а не заголовками:
- nginx —
proxy_buffering off; proxy_cache off; gzip off;для этих location, напримерlocation ~ ^/api/(ai-chat/(stream$|runs/.+/stream$)|shares/ai/) { ... } - Traefik — вести эти пути через отдельный роутер без
compress-мидлвари (compress буферизует SSE-кадры до закрытия ответа), напримерPathPrefix(`/api/ai-chat/stream`) || PathPrefix(`/api/ai-chat/runs/`). Для надёжности:traefik.http.middlewares.<name>.compress.excludedcontenttypes: text/event-stream.
Миграция с Docmost
Схема БД Gitmost — это строгий superset схемы Docmost. Все Gitmost-специфичные миграции только
добавляют новые таблицы (page_embeddings, ai_chats, ai_chat_messages,
ai_provider_credentials, ai_mcp_servers) и nullable-колонки — они никогда не удаляют и не
переписывают существующие данные Docmost. Миграции применяются автоматически при старте, поэтому
миграция существующего инстанса Docmost — это по сути замена двух образов.
Единственное жёсткое требование — образ БД: RAG-хранилище AI-агента использует расширение
pgvector (CREATE EXTENSION vector), которого нет в
стоковом образе postgres. Замените его на pgvector/pgvector:pgNN — это тот же ванильный
Postgres со встроенным pgvector, собранный на базе официального образа postgres и полностью
data-совместимый с ним.
С текущего Docmost на Postgres 18
Если ваш Docmost уже работает на postgres:18, это чистая замена in-place — без
dump/restore, существующий каталог данных переиспользуется как есть:
services:
docmost:
- image: docmost/docmost:latest
+ image: ghcr.io/vvzvlad/gitmost:latest
...
db:
- image: postgres:18
+ image: pgvector/pgvector:pg18
APP_SECRET, DATABASE_URL, REDIS_URL и том сторейджа остаются прежними. При первом запуске
новые миграции применяются поверх вашей схемы (CREATE EXTENSION vector плюс таблицы
page_embeddings и AI-таблицы); следите в логах за строками Migration "..." executed successfully.
⚠️ Никогда не меняйте
APP_SECRETпосле установки. Он выполняет двойную роль: подписывает JWT и служит материалом для ключа AES-256-GCM, которым шифруются сохранённые ключи AI-провайдеров (API-ключи). Смена секрета сделает все сохранённые AI-ключи нерасшифровываемыми (придётся вводить их заново в настройках AI) и инвалидирует все текущие сессии. Задайте его один раз, держите неизменным и бэкапьте вместе с базой данных.
Локальный сервер эмбеддингов
Семантическому (RAG) поиску AI-агента нужна модель эмбеддингов. Вместо оплаты облачного
провайдера (например, OpenAI text-embedding-3-*) за эмбеддинг каждой страницы можно запустить
небольшую open-weights модель у себя через Hugging Face
Text Embeddings Inference (TEI) — он
отдаёт OpenAI-совместимый эндпоинт /v1/embeddings. Хороший дефолт — intfloat/multilingual-e5-small:
многоязычная, 384-мерная, комфортно работает на CPU (~1–2 ГБ RAM, 1–2 vCPU). Пропишите её в
Настройки воркспейса → AI → Эмбеддинги.
Вариант A — локально (та же Docker-сеть, что и Gitmost)
Запустите TEI контейнером в той же сети, где уже работает Gitmost. Порт наружу не публикуется, поэтому эндпоинт остаётся внутренним и не требует авторизации.
services:
embeddings:
image: ghcr.io/huggingface/text-embeddings-inference:cpu-1.9 # pin version; use a cuda-* tag for GPU
container_name: embeddings
restart: unless-stopped
networks:
- gitmost_net # same network Gitmost is on
command:
- "--model-id"
- "intfloat/multilingual-e5-small"
- "--auto-truncate" # clamp over-long inputs instead of returning 413
volumes:
- tei-models:/data # weights are downloaded once and cached here
networks:
gitmost_net:
external: true # the network Gitmost already uses
volumes:
tei-models:
Настройки Gitmost (Настройки воркспейса → AI → Эмбеддинги):
| Поле | Значение |
|---|---|
| Model | intfloat/multilingual-e5-small |
| Base URL | http://embeddings:80/v1/ |
| Embedding API key | — (оставить пустым) |
embeddings— имя контейнера, Gitmost резолвит его по DNS внутри Docker-сети. Наружу порт не публикуется, эндпоинт доступен только контейнерам этой сети, поэтому авторизация не нужна.
Вариант B — на отдельном хосте (наружу через Traefik + Let's Encrypt)
Предполагается, что на хосте уже есть Traefik с ACME-резолвером (в примере ниже — letsEncrypt,
entrypoint websecure, общая сеть docker_main_net). Замените домен / сеть / резолвер на свои.
DNS: заведите A-запись embeddings.example.com → IP хоста с Traefik (тот же challenge / порт 80,
что и у остальных сайтов).
services:
embeddings:
image: ghcr.io/huggingface/text-embeddings-inference:cpu-1.9 # pin version; cuda-* tag for GPU
container_name: embeddings
restart: unless-stopped
networks:
- docker_main_net # the network Traefik is attached to
command:
- "--model-id"
- "intfloat/multilingual-e5-small"
- "--auto-truncate"
- "--api-key"
- "sk-emb-REPLACE_WITH_YOUR_KEY"
volumes:
- tei-models:/data
labels:
traefik.enable: "true"
traefik.http.routers.embeddings.rule: "Host(`embeddings.example.com`)"
traefik.http.routers.embeddings.entrypoints: "websecure"
traefik.http.routers.embeddings.tls: "true"
traefik.http.routers.embeddings.tls.certresolver: "letsEncrypt"
traefik.http.routers.embeddings.service: "embeddings"
traefik.http.services.embeddings.loadbalancer.server.port: "80"
# TEI enforces the Bearer key itself; Traefik only rate-limits to protect the CPU
traefik.http.routers.embeddings.middlewares: "embeddings-rl"
traefik.http.middlewares.embeddings-rl.ratelimit.average: "20"
traefik.http.middlewares.embeddings-rl.ratelimit.burst: "40"
traefik.http.middlewares.embeddings-rl.ratelimit.period: "1s"
networks:
docker_main_net:
external: true
volumes:
tei-models:
Настройки Gitmost (Настройки воркспейса → AI → Эмбеддинги):
| Поле | Значение |
|---|---|
| Model | intfloat/multilingual-e5-small |
| Base URL | https://embeddings.example.com/v1/ |
| Embedding API key | ваш sk-emb-… |
Проверка снаружи:
curl -s https://embeddings.example.com/v1/embeddings \
-H "Authorization: Bearer sk-emb-REPLACE_WITH_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"intfloat/multilingual-e5-small","input":"query: hello"}' \
| python3 -c 'import sys,json;print("dims:",len(json.load(sys.stdin)["data"][0]["embedding"]))'
# -> dims: 384
Заметки про сервер эмбеддингов
- Размерность вектора — 384. Если раньше этот Gitmost эмбеддился другой моделью
(например,
text-embedding-3-large= 3072-dim), старые строки в pgvector не совпадут по размерности — очистите существующие эмбеддинги / переиндексируйте перед переключением. Gitmost сравнивает только вектора одной размерности, поэтому строки другой размерности не участвуют в поиске, а не ломают его. - Первый старт тянет веса (сотни МБ) с
huggingface.coв томtei-models; дальше — из тома. - Пин версии. Пиньте образ, а при желании и модель: добавьте в
command--revision <commit-sha>(sha берётся со страницы модели на Hugging Face). - Без egress (air-gapped): засейте том
tei-modelsзаранее и добавьтеenvironment: [HF_HUB_OFFLINE=1]. - GPU: возьмите cuda-тег того же релиза (например,
ghcr.io/huggingface/text-embeddings-inference:cuda-1.9) и запустите контейнер сgpus: all.
Возможности
- Совместная работа в реальном времени
- Диаграммы (Draw.io, Excalidraw и Mermaid)
- Пространства (Spaces)
- Управление правами доступа
- Группы
- Комментарии (с резолвом / переоткрытием и всплывающими подсказками с текстом комментария при наведении)
- История страниц
- Поиск
- Вложения файлов
- Встраивания (Airtable, Loom, Miro и другие)
- Переводы (10+ языков)
- Встроенный MCP-сервер (
/mcp) - Чат с AI-агентом по вики (чтение + запись, RAG-поиск, внешние MCP / доступ в интернет); окно чата закрепляется в боковом меню, а агент узнаёт о ваших правках страницы между ходами
- Кнопки код-блока оверлеем, селектор языка появляется при наведении
- Кнопка «Ударение» (U+0301) в bubble-меню
- Позиция чтения (прокрутка) восстанавливается после перезагрузки
- Slash-меню терпимо к неправильной раскладке (ЙЦУКЕН↔QWERTY)
Скриншоты
Лицензия
Gitmost распространяется под открытой лицензией AGPL 3.0.
В отличие от upstream-Docmost, этот форк не содержит кода Enterprise-редакции — каталоги
apps/server/src/ee, apps/client/src/ee и packages/ee удалены, поэтому файлов под
enterprise-лицензией здесь нет.
Благодарности
Gitmost основан на Docmost от команды Docmost. Огромное спасибо им за оригинальный открытый проект.
Crowdin — за доступ к их платформе локализации.
Algolia — за полнотекстовый поиск по документации.


