Липки: карточка объекта (клиент Антон, Cudy TR3000 100.70.35.234, белый WAN 5.101.135.71) + рецепт Gitea→openclaw kb-pull webhook
Закрывает причину #1 путаницы Максимки на запросах вида "OpenWRT Липки": слово "Липки" во всём vault встречалось только одной строкой в netbird-inventory, FTS вытаскивал НИИКН по статистике слова "OpenWRT". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
148
snippets/openclaw-kb-webhook.md
Normal file
148
snippets/openclaw-kb-webhook.md
Normal file
@@ -0,0 +1,148 @@
|
||||
---
|
||||
date: 2026-05-06
|
||||
type: snippet
|
||||
tags: [openclaw, gitea, webhook, kb-sync]
|
||||
---
|
||||
|
||||
# Webhook Gitea → kb-pull на LXC 137 (Максимка)
|
||||
|
||||
Сократить лаг Mac → openclaw FTS с **до 15 мин** (cron `*/15`) до **<5 секунд** через push-webhook от Gitea.
|
||||
|
||||
Cron оставляем как safety net — он почти ничего не стоит и спасает, если listener умер.
|
||||
|
||||
## Архитектура
|
||||
|
||||
```
|
||||
Mac git push ──► Gitea (LXC 136, 10.0.0.189)
|
||||
│
|
||||
│ HTTP POST (push event)
|
||||
▼
|
||||
LXC 137 :18790 kb-pull-webhook (systemd)
|
||||
│
|
||||
└─► /usr/local/bin/kb-pull.sh (тот же что в cron)
|
||||
```
|
||||
|
||||
## 1. Listener `/usr/local/bin/kb-pull-webhook.py`
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
"""Слушает Gitea webhook, дёргает kb-pull.sh."""
|
||||
import hmac, hashlib, http.server, os, subprocess
|
||||
|
||||
SECRET = os.environ.get('GITEA_WEBHOOK_SECRET', '').encode()
|
||||
PULL = '/usr/local/bin/kb-pull.sh'
|
||||
|
||||
class H(http.server.BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
n = int(self.headers.get('Content-Length', 0) or 0)
|
||||
body = self.rfile.read(n)
|
||||
if SECRET:
|
||||
sig = self.headers.get('X-Gitea-Signature', '')
|
||||
mac = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
|
||||
if not hmac.compare_digest(sig, mac):
|
||||
self.send_error(401); return
|
||||
subprocess.Popen([PULL],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
self.send_response(202); self.end_headers()
|
||||
self.wfile.write(b'queued\n')
|
||||
def do_GET(self): # health-check
|
||||
self.send_response(200); self.end_headers()
|
||||
self.wfile.write(b'ok\n')
|
||||
def log_message(self, fmt, *a): # без спама в journal
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
port = int(os.environ.get('PORT', '18790'))
|
||||
http.server.HTTPServer(('0.0.0.0', port), H).serve_forever()
|
||||
```
|
||||
|
||||
```bash
|
||||
chmod +x /usr/local/bin/kb-pull-webhook.py
|
||||
```
|
||||
|
||||
## 2. systemd unit `/etc/systemd/system/kb-pull-webhook.service`
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=KB pull webhook listener (Gitea -> kb-pull.sh)
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Environment=GITEA_WEBHOOK_SECRET=CHANGE_ME_LONG_RANDOM
|
||||
Environment=PORT=18790
|
||||
ExecStart=/usr/bin/python3 /usr/local/bin/kb-pull-webhook.py
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
# Минимальные права — listener не пишет в /root, только запускает kb-pull.sh
|
||||
NoNewPrivileges=yes
|
||||
PrivateTmp=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now kb-pull-webhook.service
|
||||
systemctl status kb-pull-webhook.service
|
||||
ss -ltnp | grep 18790
|
||||
```
|
||||
|
||||
Сгенерировать секрет:
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
## 3. Webhook в Gitea UI
|
||||
|
||||
`git.dttb.ru` → репо `oleg/knowledge-base` → **Settings → Webhooks → Add Webhook → Gitea**
|
||||
|
||||
| Поле | Значение |
|
||||
|---|---|
|
||||
| Target URL | `http://10.0.0.239:18790/` |
|
||||
| HTTP Method | POST |
|
||||
| Content Type | `application/json` |
|
||||
| Secret | тот же, что в systemd unit |
|
||||
| Trigger On | Push Events |
|
||||
| Branch filter | `main` |
|
||||
| Active | ✓ |
|
||||
|
||||
Жмём **Test Delivery** — должно прилететь `202 queued`.
|
||||
|
||||
## 4. Опционально: ограничить порт по источнику
|
||||
|
||||
Listener слушает на `0.0.0.0`. Если хочется — закрыть всё кроме Gitea LXC 136:
|
||||
|
||||
```bash
|
||||
iptables -A INPUT -p tcp --dport 18790 -s 10.0.0.189 -j ACCEPT
|
||||
iptables -A INPUT -p tcp --dport 18790 -j DROP
|
||||
# или через nftables / netbird ACL — на вкус
|
||||
```
|
||||
|
||||
## 5. Проверка end-to-end
|
||||
|
||||
```bash
|
||||
# на Mac
|
||||
cd ~/knowledge-base
|
||||
date >> /tmp/test && git add -A && git commit -m "webhook test" && git push
|
||||
|
||||
# на LXC 137 — должна появиться свежая строка
|
||||
pct exec 137 -- tail -3 /var/log/kb-pull.log
|
||||
```
|
||||
|
||||
## Откат
|
||||
|
||||
```bash
|
||||
systemctl disable --now kb-pull-webhook.service
|
||||
rm /etc/systemd/system/kb-pull-webhook.service
|
||||
rm /usr/local/bin/kb-pull-webhook.py
|
||||
# в Gitea — деактивировать webhook
|
||||
```
|
||||
|
||||
Cron `*/15` остаётся живым — KB продолжит синкаться по таймеру.
|
||||
|
||||
## Замечания
|
||||
|
||||
- **`openclaw memory` не переиндексируется автоматически** после `kb-pull`. Бот видит markdown сразу (он читает из FS), но FTS-индекс в `~/.openclaw/memory/main.sqlite` обновляется при следующем reindex-цикле. Если нужно ускорить — после pull можно дёргать `openclaw memory rebuild --incremental` (проверить наличие команды в текущей версии). Это уже отдельный шаг — добавить в `kb-pull.sh` после успешного `git pull`.
|
||||
- На LXC 137 `kb-pull.sh` — простой ff-only с авто-reset при divergence. Webhook на нём ничего не ломает: тот же скрипт, та же блокировка `/tmp/kb-pull.lock`.
|
||||
Reference in New Issue
Block a user