Files
zuevav f4bca8449e main
2026-05-20 19:33:02 +03:00

363 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Deployment Guide
Полная инструкция по развёртыванию ZBrain с нуля.
## Стадия 1: Подготовка VM
### Спецификация
| Параметр | Значение |
|----------|----------|
| ОС | Ubuntu 22.04 LTS Server |
| CPU | 4 vCPU (минимум 2) |
| RAM | 8 GB (минимум 4) |
| Disk | 80 GB SSD (минимум 40) |
| FS | ext4 |
| Network | статический IP в сети ZETIT |
### Создание
1. На гипервизоре создать VM с указанными параметрами
2. Установить Ubuntu 22.04 LTS Server (minimal)
3. Создать пользователя `admin` с sudo правами
4. Скопировать SSH-ключи: `ssh-copy-id admin@<ip>`
5. Отключить password auth: `sudo passwd -l root` и в `/etc/ssh/sshd_config` `PasswordAuthentication no`
### Базовая конфигурация
```bash
# Hostname
sudo hostnamectl set-hostname zbrain
echo "127.0.1.1 zbrain.zetit.local zbrain" | sudo tee -a /etc/hosts
# Часовой пояс
sudo timedatectl set-timezone Europe/Moscow
# Обновления
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y unattended-upgrades
```
### DNS
В твоей внутренней DNS зоне (zetit.local или эквивалент):
```
brain.zetit.local. A <internal-ip>
```
На внешнем DNS (если используешь публичный контур):
```
brain.zetit.ru. A <external-ip-of-edge-server>
```
Edge-сервер (где живёт nginx с публичным контуром) проксирует на внутренний IP VM.
## Стадия 2: Bootstrap
```bash
# Склонируй ZBrain repo
sudo mkdir -p /opt/zbrain && sudo chown $USER:$USER /opt/zbrain
git clone git@git.zetit.ru:zuevav/ZBrain.git /opt/zbrain
cd /opt/zbrain
# Зеркало gbrain (один раз, не на каждой VM)
# Это делается единожды на твоей рабочей машине:
#
# git clone --mirror https://github.com/garrytan/gbrain.git
# cd gbrain.git
# git push --mirror git@git.zetit.ru:zuevav/gbrain-mirror.git
# Запусти bootstrap
sudo TOTAL_RAM_GB=8 FNA_PROXY="http://client_001:PASSWORD@fna.zetit.ru:3128" bash scripts/bootstrap-vm.sh
```
После завершения скрипт покажет следующие шаги.
## Стадия 3: Postgres secrets
```bash
sudo -u postgres psql
```
```sql
-- Пароль root postgres юзера (сохрани в KeePass)
ALTER USER postgres PASSWORD 'STRONG_RANDOM_PASSWORD_24_CHARS';
-- Пользователь для brainhub
CREATE USER brainhub WITH PASSWORD 'ANOTHER_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE brainhub TO brainhub;
-- Проверка
\du
\l
\q
```
## Стадия 4: Заполнение .env
```bash
sudo cp /etc/zbrain/env.example /etc/zbrain/.env
sudo chmod 600 /etc/zbrain/.env
sudo chown zbrain:zbrain /etc/zbrain/.env
sudo nano /etc/zbrain/.env
```
Сгенерируй секреты:
```bash
# SESSION_SECRET
openssl rand -hex 32
# JWT_SECRET
openssl rand -hex 32
# TOKEN_ENCRYPTION_KEY (для шифрования TOTP секретов)
openssl rand -hex 16
```
Заполни:
- `DATABASE_URL` — с паролем brainhub
- Секреты выше
- `OPENAI_API_KEY` и `ANTHROPIC_API_KEY`
- FNA-прокси с реальными credentials
- `INITIAL_OWNER_EMAIL` и `INITIAL_OWNER_PASSWORD` (временный, сменишь после первого логина)
## Стадия 5: Первый брейн
```bash
sudo bash /opt/zbrain/scripts/create-brain.sh zetit "ZETIT MSP" 3001
```
Скрипт:
1. Создаст пользователя `gbrain_zetit` и БД `gbrain_zetit` в Postgres
2. Положит конфиг в `/var/lib/zbrain/brains/zetit/`
3. Запустит миграции gbrain
4. Создаст и запустит systemd unit `zbrain-gbrain-zetit`
Проверка:
```bash
systemctl status zbrain-gbrain-zetit
journalctl -u zbrain-gbrain-zetit -f # в отдельном окне
curl http://localhost:3001/health
```
## Стадия 6: Импорт первых данных
```bash
sudo -u zbrain bash -c '
export PATH=$HOME/.bun/bin:$PATH
source /etc/zbrain/.env
cd /var/lib/zbrain/gbrain
bun run gbrain import /path/to/your/markdown/files
'
```
Проверка:
```bash
sudo -u postgres psql -d gbrain_zetit -c '
SELECT
(SELECT count(*) FROM pages) AS pages,
(SELECT count(*) FROM content_chunks) AS chunks,
(SELECT count(*) FROM content_chunks WHERE embedding IS NOT NULL) AS embedded;
'
```
## Стадия 7: Brainhub API + Web
> Эта часть требует, чтобы код Sprint 2-5 был написан. До этого пропускаем.
### Build
```bash
cd /opt/zbrain
sudo -u zbrain bun install
sudo -u zbrain bun run build
```
### Миграции
```bash
sudo -u zbrain bun run --cwd apps/api db:migrate
```
### Запуск через docker-compose (рекомендуется в prod)
```bash
cd /opt/zbrain/deploy/docker
sudo docker compose up -d
sudo docker compose ps
```
### Альтернатива: systemd
Если не хочешь docker - использовать `deploy/systemd/zbrain-brainhub.service`.
## Стадия 8: Nginx (внутренний контур)
```bash
sudo apt-get install -y nginx
# Скопируй конфиг
sudo cp /opt/zbrain/deploy/nginx/zbrain.conf /etc/nginx/sites-available/zbrain
# Закомментируй временно public server-блок (TLS пока нет)
sudo ln -s /etc/nginx/sites-available/zbrain /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
# Проверь
sudo nginx -t
# Запусти
sudo systemctl reload nginx
```
Тест:
```bash
curl -H "Host: brain.zetit.local" http://localhost/
```
## Стадия 9: TLS для публичного контура
> Только если у тебя есть edge-сервер с внешним IP и DNS-запись brain.zetit.ru указывает на него.
На edge-сервере (или на самой VM, если она имеет внешний IP):
```bash
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d brain.zetit.ru
```
Раскомментируй public server-блок в nginx и перезагрузи.
## Стадия 10: Первый логин
1. Открой http://brain.zetit.local в браузере
2. Залогинься как `INITIAL_OWNER_EMAIL` / `INITIAL_OWNER_PASSWORD`
3. **Сразу смени пароль** в Profile
4. Включи 2FA (когда Sprint 7 готов)
5. Удали `INITIAL_OWNER_*` из `.env` (необязательно, но гигиенично)
## Стадия 11: Подключение Claude Code
1. В UI: создай токен с scope `mcp:write:zetit`
2. Скопируй токен
3. На своей рабочей машине добавь в `~/.claude/mcp.json` или в `.claude/mcp.json` проекта:
```json
{
"mcpServers": {
"zbrain-zetit": {
"transport": "http",
"url": "http://brain.zetit.local/mcp/zetit",
"headers": {
"Authorization": "Bearer brain_pat_<your-token>"
}
}
}
}
```
4. Перезапусти Claude Code
5. Проверь что MCP-инструменты доступны
## Стадия 12: Backup
```bash
# Создай age ключ для шифрования бэкапов (только один раз!)
age-keygen -o /tmp/backup.age
cat /tmp/backup.age # сохрани оба ключа в KeePass!
# Положи публичную часть на VM
sudo head -1 /tmp/backup.age | grep public | awk '{print $NF}' > /tmp/pub
sudo mv /tmp/pub /etc/zbrain/backup.age.pub
sudo chmod 644 /etc/zbrain/backup.age.pub
# Удали /tmp/backup.age с VM!
shred -u /tmp/backup.age
# Тест бэкапа
sudo bash /opt/zbrain/scripts/backup.sh
# Добавь в cron
sudo crontab -e
# Добавь строку:
# 0 3 * * * /opt/zbrain/scripts/backup.sh >> /var/log/zbrain/backup.log 2>&1
```
## Чек-лист готовности
- [ ] VM создана с правильными параметрами
- [ ] Bootstrap отработал без ошибок
- [ ] Postgres работает, пароли установлены
- [ ] `.env` заполнен и защищён 600
- [ ] Первый брейн создан и работает
- [ ] Данные импортированы
- [ ] Brainhub запущен и доступен через nginx
- [ ] OAuth настроен (если нужно)
- [ ] TLS работает (если публичный контур)
- [ ] Owner логин работает, пароль сменён
- [ ] Claude Code успешно подключается через токен
- [ ] Backup делается и шифруется
- [ ] Восстановление из бэкапа протестировано (на отдельной VM)
- [ ] Мониторинг настроен (опционально)
- [ ] Документация в `docs/INFRASTRUCTURE.md` обновлена
## Типовые проблемы
### gbrain не стартует
```bash
journalctl -u zbrain-gbrain-zetit -n 50 --no-pager
```
Частые причины:
- Пароль в DATABASE_URL не совпадает
- FNA-прокси недоступен
- Bun не в PATH (проверь Environment="PATH=..." в unit-файле)
### Embeddings не создаются
```bash
# Проверь подключение к OpenAI через FNA
sudo -u zbrain bash -c '
source /etc/zbrain/.env
curl --proxy "$HTTPS_PROXY" https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"
'
```
### Postgres падает
```bash
# Проверь логи
sudo tail -100 /var/log/postgresql/postgresql-16-main.log
# Проверь disk space
df -h /var/lib/postgresql/
# Проверь shared_buffers vs RAM
sudo -u postgres psql -c 'SHOW shared_buffers; SHOW effective_cache_size;'
```
### Брейн занимает слишком много места
```bash
# Размер по таблицам
sudo -u postgres psql -d gbrain_zetit -c "
SELECT
schemaname || '.' || tablename AS table,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;
"
```
Если эмбеддинги занимают слишком много — можно перейти на `text-embedding-3-small` (вместо `large`), это даст 1536 → 1024 dim и -33% места.