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
+50
View File
@@ -0,0 +1,50 @@
# ZBrain Development Docker Compose
#
# Только Postgres - всё остальное запускается нативно через bun/node.
#
# Запуск:
# docker compose -f deploy/docker/docker-compose.dev.yml up -d
#
# Подключение:
# psql postgresql://zbrain:dev@localhost:5432/brainhub_dev
version: "3.9"
services:
postgres:
image: pgvector/pgvector:pg16
container_name: zbrain-postgres-dev
restart: unless-stopped
environment:
POSTGRES_USER: zbrain
POSTGRES_PASSWORD: dev
POSTGRES_DB: brainhub_dev
ports:
- "127.0.0.1:5432:5432"
volumes:
- postgres-dev-data:/var/lib/postgresql/data
- ./init-dev.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U zbrain"]
interval: 5s
timeout: 3s
retries: 5
# Опционально - adminer для просмотра БД через браузер
adminer:
image: adminer:latest
container_name: zbrain-adminer-dev
restart: unless-stopped
ports:
- "127.0.0.1:8081:8080"
environment:
ADMINER_DEFAULT_SERVER: postgres
ADMINER_DESIGN: pepa-linha-dark
volumes:
postgres-dev-data:
driver: local
+78
View File
@@ -0,0 +1,78 @@
# ZBrain Production Docker Compose
#
# Запуск:
# docker compose -f deploy/docker/docker-compose.yml up -d
#
# Postgres работает на хосте (не в контейнере) - так проще делать
# нативный pg_dump, тюнинг и обновления без даунтайма всех брейнов.
# gbrain instances тоже работают через systemd на хосте.
# В контейнерах - только brainhub (api + web) и nginx.
version: "3.9"
services:
# ============================================================
# Brainhub API (Node.js + Express)
# ============================================================
brainhub-api:
build:
context: ../..
dockerfile: deploy/docker/api.Dockerfile
image: zbrain/brainhub-api:latest
container_name: zbrain-api
restart: unless-stopped
# Postgres на хосте, поэтому используем host network для api
# ИЛИ - оставляем bridge и в DATABASE_URL пишем host.docker.internal
network_mode: host
env_file:
- /etc/zbrain/.env
environment:
NODE_ENV: production
LOG_FILE: /var/log/zbrain/brainhub.log
volumes:
- /var/log/zbrain:/var/log/zbrain
- /etc/zbrain:/etc/zbrain:ro
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
# ============================================================
# Brainhub Web (статика через nginx внутри контейнера)
# ============================================================
brainhub-web:
build:
context: ../..
dockerfile: deploy/docker/web.Dockerfile
image: zbrain/brainhub-web:latest
container_name: zbrain-web
restart: unless-stopped
ports:
- "127.0.0.1:8080:80" # только localhost, внешний доступ через системный nginx
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
# ============================================================
# Networks
# ============================================================
# brainhub-api использует host network для прямого доступа к Postgres
# и к gbrain instances (localhost:3001-3099).
# brainhub-web стоит на bridge с port forward на 127.0.0.1:8080.
+17
View File
@@ -0,0 +1,17 @@
-- ZBrain Dev Postgres Init
-- Создаёт расширения и тестовые БД для локальной разработки
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Тестовая БД для gbrain
CREATE DATABASE gbrain_dev OWNER zbrain;
\c gbrain_dev
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
\c brainhub_dev
-- В brainhub_dev расширения уже созданы выше, миграции прокатятся через приложение
+189
View File
@@ -0,0 +1,189 @@
# ZBrain Nginx Configuration
# ===========================
# Два server-блока:
# 1. Внутренний (brain.zetit.local) - полный доступ к UI и API
# 2. Публичный (brain.zetit.ru) - только /mcp/* и /oauth/*
#
# Положить в /etc/nginx/sites-available/zbrain
# и сделать symlink в /etc/nginx/sites-enabled/
# ============================================================
# Upstream'ы
# ============================================================
upstream brainhub_api {
server 127.0.0.1:3000;
keepalive 32;
}
upstream brainhub_api_public {
server 127.0.0.1:3010;
keepalive 32;
}
upstream brainhub_web {
server 127.0.0.1:8080;
keepalive 32;
}
# Rate limiting для публичного MCP
limit_req_zone $binary_remote_addr zone=mcp_public:10m rate=30r/s;
limit_req_zone $http_authorization zone=mcp_token:10m rate=100r/s;
# ============================================================
# Внутренний контур: brain.zetit.local
# ============================================================
server {
listen 80;
listen [::]:80;
server_name brain.zetit.local;
# Внутри сети можно без HTTPS, либо self-signed cert
# Если нужен HTTPS - раскомментировать listen 443 ниже и убрать listen 80
access_log /var/log/nginx/zbrain-internal.access.log;
error_log /var/log/nginx/zbrain-internal.error.log;
client_max_body_size 50M;
# Web UI (статика)
location / {
proxy_pass http://brainhub_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# API
location /api/ {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# Таймауты для долгих операций (sync, import)
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
# SSE events
location /api/events {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 24h;
# SSE headers
chunked_transfer_encoding off;
}
# MCP - внутренний доступ (тоже с токенами, но без rate limit)
location /mcp/ {
proxy_pass http://brainhub_api;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization $http_authorization;
proxy_read_timeout 120s;
proxy_buffering off;
}
}
# ============================================================
# Публичный контур: brain.zetit.ru
# ============================================================
server {
listen 80;
listen [::]:80;
server_name brain.zetit.ru;
# HTTP -> HTTPS redirect (кроме ACME challenge)
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name brain.zetit.ru;
# TLS
ssl_certificate /etc/letsencrypt/live/brain.zetit.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/brain.zetit.ru/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
access_log /var/log/nginx/zbrain-public.access.log;
error_log /var/log/nginx/zbrain-public.error.log;
client_max_body_size 10M;
# ВАЖНО: на публичном контуре доступны только /mcp/* и /oauth/*
# Никакого UI, API админки и т.д.
# MCP proxy с rate limiting
location /mcp/ {
# Лимит по IP - защита от подбора токенов
limit_req zone=mcp_public burst=60 nodelay;
# Лимит по токену - защита от взбесившегося скрипта
limit_req zone=mcp_token burst=200 nodelay;
limit_req_status 429;
proxy_pass http://brainhub_api_public;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization $http_authorization;
proxy_read_timeout 120s;
proxy_buffering off;
}
# OAuth flow для удалённой авторизации
location /oauth/ {
limit_req zone=mcp_public burst=20 nodelay;
proxy_pass http://brainhub_api_public;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Health check (без rate limit, для мониторинга)
location /health {
proxy_pass http://brainhub_api_public/health;
access_log off;
}
# Всё остальное - 404, чтобы публично ничего лишнего не светить
location / {
return 404;
}
}