This commit is contained in:
zuevav
2026-05-20 19:33:02 +03:00
commit f4bca8449e
30 changed files with 4152 additions and 0 deletions
+319
View File
@@ -0,0 +1,319 @@
# Operations Guide
Документ для оператора ZBrain (admin) — повседневные задачи, типовые проблемы, runbook.
## Чек-лист после деплоя
После завершения [DEPLOYMENT.md](DEPLOYMENT.md):
- [ ] Все systemd unit'ы для брейнов активны: `systemctl status 'zbrain-gbrain-*'`
- [ ] Docker контейнеры brainhub запущены: `docker compose -f /opt/zbrain/deploy/docker/docker-compose.yml ps`
- [ ] Nginx обслуживает оба домена: `curl -H "Host: brain.zetit.local" http://localhost/health`
- [ ] Cron для backup'ов настроен: `sudo crontab -l | grep backup`
- [ ] Логи пишутся: `ls -lh /var/log/zbrain/`
- [ ] Disk usage в норме: `df -h /var/lib/postgresql /var/lib/zbrain /var/log`
## Ежедневные задачи (автоматические)
### Backup (cron, 03:00)
```cron
0 3 * * * root /opt/zbrain/scripts/backup.sh
```
Что проверять раз в неделю:
- `ls -lh /var/backups/zbrain/` — есть свежий бэкап
- `cat /var/log/zbrain/backup.log | tail -20` — нет ошибок
- Раз в месяц — тестовое восстановление на отдельной VM
### Sync (опционально, cron, 06:00 / 18:00)
Если источники не настроены через UI с расписанием, можно запускать вручную через scripts/sync-all.sh (будет добавлено в Sprint 4).
## Типовые задачи
### Создать нового пользователя
Через UI:
1. Залогинься как owner
2. /users → New user
3. Email + role (admin / editor / viewer)
4. Скопировать temp password из ответа
Через CLI (только owner):
```bash
sudo docker exec zbrain-api node -e '
// TODO: команда будет добавлена в Sprint 7
'
```
### Создать новый брейн
```bash
sudo bash /opt/zbrain/scripts/create-brain.sh <name> "<display name>" <port>
# Пример
sudo bash /opt/zbrain/scripts/create-brain.sh fontvielle "Fontvielle Infrastructure" 3005
```
### Импорт большого корпуса в брейн
```bash
sudo -u zbrain bash -c '
export PATH=$HOME/.bun/bin:$PATH
source /etc/zbrain/.env
export DATABASE_URL=$(cat /var/lib/zbrain/brains/zetit/config.json | jq -r .database_url)
cd /var/lib/zbrain/gbrain
bun run gbrain import /path/to/markdown/
'
```
Для очень больших корпусов (>10000 страниц) — лучше через UI после Sprint 4, там SSE прогресс.
### Обновить gbrain до новой версии
1. **На рабочей машине** (с GitHub доступом):
```bash
git clone --bare https://github.com/garrytan/gbrain.git
cd gbrain.git
git push --mirror git@git.zetit.ru:zuevav/gbrain-mirror.git
```
2. **На VM ZBrain** — проверить changelog upstream'а на breaking changes, особенно в БД схеме.
3. Создать ADR в `docs/DECISIONS/` если есть значимые изменения.
4. Останавливаем все брейны:
```bash
sudo systemctl stop 'zbrain-gbrain-*'
```
5. Обновляем gbrain:
```bash
sudo -u zbrain bash -c '
cd /var/lib/zbrain/gbrain
git fetch
git checkout v0.27.0 # новая версия
export PATH=$HOME/.bun/bin:$PATH
export HTTPS_PROXY=$(grep HTTPS_PROXY /etc/zbrain/.env | cut -d= -f2-)
bun install
'
```
6. Применяем миграции каждого брейна:
```bash
for brain in zetit telerapharma personal community; do
sudo -u zbrain bash -c "
export PATH=\$HOME/.bun/bin:\$PATH
export DATABASE_URL=\$(cat /var/lib/zbrain/brains/$brain/config.json | jq -r .database_url)
cd /var/lib/zbrain/gbrain
bun run gbrain migrate
"
done
```
7. Запускаем брейны:
```bash
sudo systemctl start 'zbrain-gbrain-*'
```
8. Проверяем health.
### Восстановление из бэкапа
См. `scripts/restore.sh`. Краткая инструкция:
```bash
sudo bash /opt/zbrain/scripts/restore.sh 20260520-031500
# спросит путь к age приватному ключу
```
**ВАЖНО:** после restore удалить age ключ с VM:
```bash
shred -u /tmp/backup.age
```
### Реактивация заблокированного пользователя
Если пользователь забыл пароль или нужно сбросить:
```sql
-- Через UI пока нет, делаем напрямую
sudo -u postgres psql -d brainhub
-- Сгенерировать новый bcrypt hash (cost=12)
-- Можно через: echo 'newpassword' | htpasswd -bnBC 12 "" -
UPDATE users
SET password_hash = '<new-bcrypt-hash>',
must_change_password = true
WHERE email = 'user@example.com';
```
### Срочный отзыв токена
Если подозрение на утечку токена и нельзя ждать 30 секунд кэша:
```bash
# Через UI: /tokens → Revoke. Это уже делает invalidate cache.
# Срочное через API:
curl -X POST http://brain.zetit.local/api/admin/cache/invalidate-token \
-H "Authorization: Bearer <admin-session-token>" \
-H "Content-Type: application/json" \
-d '{"tokenPrefix":"brain_pat_a8f3"}'
# Полный сброс кэша токенов (drastic):
sudo systemctl restart docker
sudo docker compose restart brainhub-api
```
## Мониторинг
### Что смотреть в /var/log/zbrain/
```bash
# Live tail всех логов
sudo tail -F /var/log/zbrain/*.log
# Ошибки за последний час
sudo journalctl --since "1 hour ago" -u 'zbrain-gbrain-*' | grep -i error
# Brainhub access pattern
sudo tail -1000 /var/log/zbrain/brainhub.log | jq -r 'select(.req.url) | "\(.time) \(.req.method) \(.req.url) → \(.res.statusCode)"'
```
### Метрики Postgres
```bash
# Connection count
sudo -u postgres psql -c 'SELECT count(*), state FROM pg_stat_activity GROUP BY state;'
# Размер БД
sudo -u postgres psql -c "
SELECT datname, pg_size_pretty(pg_database_size(datname))
FROM pg_database WHERE datname IN ('brainhub','gbrain_zetit','gbrain_telerapharma','gbrain_personal','gbrain_community')
ORDER BY pg_database_size(datname) DESC;
"
# Топ медленных запросов
sudo -u postgres psql -c '
SELECT calls, mean_exec_time, query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC LIMIT 10;
' # если pg_stat_statements включён
```
### Disk usage
```bash
# По брейнам
du -sh /var/lib/zbrain/brains/*/
# Postgres data
sudo du -sh /var/lib/postgresql/16/main/
# Логи
sudo du -sh /var/log/zbrain/ /var/log/postgresql/ /var/log/nginx/
```
Если /var/log пухнет — настроить logrotate.
## Runbook'и инцидентов
### Сценарий: брейн не отвечает на MCP запросы
**Симптомы:** Claude Code получает 502 от /mcp/<brain>, в UI брейн помечен красным.
```bash
# 1. Проверить systemd unit
sudo systemctl status zbrain-gbrain-<brain>
# 2. Если down - последние логи
sudo journalctl -u zbrain-gbrain-<brain> -n 100 --no-pager
# 3. Если crash loop - проверить Postgres connection
sudo -u postgres psql -d gbrain_<brain> -c 'SELECT version()'
# 4. Если ОК - перезапустить
sudo systemctl restart zbrain-gbrain-<brain>
# 5. Если не помогло - временно отключить и эскалировать
sudo systemctl stop zbrain-gbrain-<brain>
```
### Сценарий: Postgres недоступен
**Симптомы:** brainhub возвращает 503, все брейны лежат.
```bash
# 1. Статус
sudo systemctl status postgresql
# 2. Если crashed - проверить логи
sudo tail -200 /var/log/postgresql/postgresql-16-main.log
# 3. Частые причины:
# a) Disk full → освободить место (старые WAL, логи)
df -h /var/lib/postgresql
sudo du -sh /var/lib/postgresql/16/main/pg_wal/
# b) OOM → проверить dmesg
sudo dmesg | tail -50 | grep -i 'killed process'
# c) Corrupt → restore из бэкапа
```
### Сценарий: исчерпался лимит OpenAI/Anthropic API
**Симптомы:** sync падает с 429, новые pages не получают embeddings.
```bash
# Проверка через FNA прокси
sudo -u zbrain bash -c '
source /etc/zbrain/.env
curl --proxy "$HTTPS_PROXY" \
https://api.openai.com/v1/dashboard/billing/usage \
-H "Authorization: Bearer $OPENAI_API_KEY"
'
# Действия:
# 1. Пополнить баланс на платформе OpenAI/Anthropic
# 2. Или временно поставить на паузу автоматический sync
# 3. Прикинуть стоимость re-embed: ~$0.65 на 7500 страниц для text-embedding-3-large
```
### Сценарий: подозрение на утечку токена
```bash
# 1. Найти токен в UI: /tokens → найти по prefix
# 2. Посмотреть активность: /audit?actor_type=token&actor_id=<id>
# 3. Revoke + invalidate cache
# 4. Создать новый токен с теми же scope, передать пользователю
# 5. Анализ через audit log:
sudo -u postgres psql -d brainhub -c "
SELECT created_at, ip, action, payload
FROM audit_log
WHERE actor_type='token' AND actor_id='<token-id>'
ORDER BY created_at DESC LIMIT 100;
"
# 6. Если был доступ из неожиданного IP - эскалация (анализ что было прочитано/изменено)
```
## Регулярные процедуры
### Раз в неделю
- Проверить freshness бэкапов и логи backup.log
- Проверить disk usage
- Глянуть audit log на необычную активность
### Раз в месяц
- Тестовый restore на отдельной VM
- Review обновлений gbrain upstream
- Обновить ОС (`apt update && apt upgrade`)
- Rotate session secrets (опционально, но повышает security posture)
### Раз в квартал
- Penetration test публичного контура (хотя бы на nikto/zap-baseline)
- Review активных токенов, удаление неиспользуемых
- Review активных пользователей, удаление неактивных
- Capacity planning: смотреть рост БД и проектировать апгрейд VM при необходимости