--- date: 2026-05-06 type: decision tags: [openclaw, gitea, webhook, kb-sync, performance] status: applied --- # Webhook Gitea → openclaw kb-pull (Фаза 2 плана улучшения KB-поиска) ## Контекст После публикации `projects/lipki/README.md` стало видно, что openclaw (Максимка) видит новые правки vault только через cron `*/15` — лаг до 15 минут. Это первое, что бьёт по UX («только что записал → бот всё ещё не знает»). План улучшения KB-поиска расписан в чате с Claude Code 2026-05-06 утром, Фаза 2 — webhook + автоматический FTS-реиндекс. ## Решение Push-канал Gitea → listener на LXC 137 → `kb-pull.sh` → `openclaw memory index`. Cron `*/15` оставлен как safety net. Подробная реализация — [[../snippets/openclaw-kb-webhook]]. ## Что развёрнуто | Компонент | Где | |---|---| | `/usr/local/bin/kb-pull-webhook.py` | LXC 137, Python http.server, HMAC-SHA256 проверка, journal-лог | | `/etc/systemd/system/kb-pull-webhook.service` | LXC 137, system unit, Restart=on-failure, secret в env | | Обновлённый `/usr/local/bin/kb-pull.sh` | `flock -w 180`, hash-diff, авто `openclaw memory index` при новом HEAD | | Webhook в Gitea (id=1, репо `oleg/knowledge-base`) | events: push, branch: main, secret в HMAC | | `webhook.ALLOWED_HOST_LIST = 10.0.0.0/24,*.dttb.ru,private` в `app.ini` | LXC 136 (Gitea в docker), `/opt/gitea/data/gitea/conf/app.ini` | ## Метрика End-to-end push → видно боту: | Этап | Время | |---|---| | `git push` с Mac → Gitea ack | ~2 c | | Gitea → webhook listener | ~3 c | | listener → kb-pull.sh → git pull → новый HEAD | ~6 c | | **Итого до видимости HEAD на 137** | **~11 c** | | FTS reindex (875 файлов / 1791 chunk) | +38 c | | **Итого до видимости в `openclaw memory search`** | **~50 c** | Было: до 15 минут (cron */15) + до 38 c reindex (если бы он раньше был) = до **~16 минут**. Улучшение: **×20 латентности до видимости HEAD, ×16 до полного FTS**. ## Грабли (для будущей памяти) 1. **Gitea SSRF-protection.** Без `ALLOWED_HOST_LIST` Gitea silently отказывает доставлять webhook на private IP. Test delivery возвращает `204`, но в Gitea log: `webhook can only call allowed HTTP servers, deny '10.0.0.239'`. Listener при этом не видит ничего — пустой journal. Это была первая причина почему ничего не работало. 2. **`flock -n` теряет вторую серию push'ов.** Если webhook прилетел во время уже идущего pull/reindex (быстрый двойной push) — non-blocking flock молча выходит. Надо `-w 180` (ждать в очереди до 3 мин). 3. **sed по строке с `||` ломается, если разделитель `|`.** `sed -i 's|flock -n|flock -w 180|'` падает с `unknown option to s`. Использовать `#` или другой разделитель — `sed -i 's#flock -n#flock -w 180#'`. 4. **Listener `log_message: pass` гасит **все** логи http.server.** Если хочется видеть приём POST — переопределить как `sys.stderr.write(...)`. Иначе debug невозможен. ## Альтернативы, которые отвергнуты - **Полностью убрать cron**: рискованно — если listener умер и не заметили, vault зависнет. Cron `*/15` ничего не стоит и страхует. - **Webhook напрямую через NPM/публичный URL**: лишний хоп, нужен HTTPS, всё в LAN — не нужно. - **iptables на 18790**: HMAC-secret уже отсекает левые запросы. Homelab trusted. Не делал. ## Откат См. секцию «Откат» в [[../snippets/openclaw-kb-webhook]]. Один rm-рецепт + удаление webhook через Gitea API. ## Что дальше Фаза 1 плана (embeddings ollama × bge-m3) — пока **отложена**. При попытке развёртывания openclaw 2026.5.2 со всеми правильными config-полями (`provider=ollama`, `remote.baseUrl`, `model=bge-m3`, `chunking.tokens=512`) **игнорирует chunking** и шлёт в `/api/embed` файлы целиком — output buffer ollama растёт до 700+ MB, обработка >5 мин, undici fetch падает по дефолтному 5-min Headers Timeout. Конфигурация откачена, состояние FTS-only сохранено. Возможные пути возврата к векторному поиску: - `provider: local` (transformers.js встроенный) — попробовать без сетевого хопа - Ждать openclaw 2026.5.3+ с фиксом chunking - GitHub Copilot embeddings (требует токен) Следующая фаза по плану — **Фаза 3** (`audit/objects-map.json` + `projects/_index.md`) или **Фаза 5.1** (слить дубли видеонаблюдения).