main
This commit is contained in:
@@ -0,0 +1,362 @@
|
||||
# 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% места.
|
||||
Reference in New Issue
Block a user