10 KiB
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 |
Создание
- На гипервизоре создать VM с указанными параметрами
- Установить Ubuntu 22.04 LTS Server (minimal)
- Создать пользователя
adminс sudo правами - Скопировать SSH-ключи:
ssh-copy-id admin@<ip> - Отключить password auth:
sudo passwd -l rootи в/etc/ssh/sshd_configPasswordAuthentication no
Базовая конфигурация
# 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
# Склонируй 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
sudo -u postgres psql
-- Пароль 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
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
Сгенерируй секреты:
# 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: Первый брейн
sudo bash /opt/zbrain/scripts/create-brain.sh zetit "ZETIT MSP" 3001
Скрипт:
- Создаст пользователя
gbrain_zetitи БДgbrain_zetitв Postgres - Положит конфиг в
/var/lib/zbrain/brains/zetit/ - Запустит миграции gbrain
- Создаст и запустит systemd unit
zbrain-gbrain-zetit
Проверка:
systemctl status zbrain-gbrain-zetit
journalctl -u zbrain-gbrain-zetit -f # в отдельном окне
curl http://localhost:3001/health
Стадия 6: Импорт первых данных
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
'
Проверка:
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
cd /opt/zbrain
sudo -u zbrain bun install
sudo -u zbrain bun run build
Миграции
sudo -u zbrain bun run --cwd apps/api db:migrate
Запуск через docker-compose (рекомендуется в prod)
cd /opt/zbrain/deploy/docker
sudo docker compose up -d
sudo docker compose ps
Альтернатива: systemd
Если не хочешь docker - использовать deploy/systemd/zbrain-brainhub.service.
Стадия 8: Nginx (внутренний контур)
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
Тест:
curl -H "Host: brain.zetit.local" http://localhost/
Стадия 9: TLS для публичного контура
Только если у тебя есть edge-сервер с внешним IP и DNS-запись brain.zetit.ru указывает на него.
На edge-сервере (или на самой VM, если она имеет внешний IP):
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d brain.zetit.ru
Раскомментируй public server-блок в nginx и перезагрузи.
Стадия 10: Первый логин
- Открой http://brain.zetit.local в браузере
- Залогинься как
INITIAL_OWNER_EMAIL/INITIAL_OWNER_PASSWORD - Сразу смени пароль в Profile
- Включи 2FA (когда Sprint 7 готов)
- Удали
INITIAL_OWNER_*из.env(необязательно, но гигиенично)
Стадия 11: Подключение Claude Code
- В UI: создай токен с scope
mcp:write:zetit - Скопируй токен
- На своей рабочей машине добавь в
~/.claude/mcp.jsonили в.claude/mcp.jsonпроекта:
{
"mcpServers": {
"zbrain-zetit": {
"transport": "http",
"url": "http://brain.zetit.local/mcp/zetit",
"headers": {
"Authorization": "Bearer brain_pat_<your-token>"
}
}
}
}
- Перезапусти Claude Code
- Проверь что MCP-инструменты доступны
Стадия 12: Backup
# Создай 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 не стартует
journalctl -u zbrain-gbrain-zetit -n 50 --no-pager
Частые причины:
- Пароль в DATABASE_URL не совпадает
- FNA-прокси недоступен
- Bun не в PATH (проверь Environment="PATH=..." в unit-файле)
Embeddings не создаются
# Проверь подключение к 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 падает
# Проверь логи
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;'
Брейн занимает слишком много места
# Размер по таблицам
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% места.