🔒 КРИТИЧНО: Видалено паролі/API ключі з документів + закрито NodePort
Some checks failed
Build and Deploy Docs / build-and-deploy (push) Has been cancelled

- Видалено всі паролі та API ключі з документів
- Замінено на посилання на Vault
- Закрито NodePort для Memory Service (тільки internal)
- Створено SECURITY-ROTATION-PLAN.md
- Створено ARCHITECTURE-150-NODES.md (план для 150 нод)
- Оновлено config.py (видалено hardcoded Cohere key)
This commit is contained in:
Apple
2026-01-10 09:46:03 -08:00
parent f7bf935a21
commit 3478dfce5f
5 changed files with 370 additions and 17 deletions

268
ARCHITECTURE-150-NODES.md Normal file
View File

@@ -0,0 +1,268 @@
# 🏗️ Архітектура для 150 нод — DAARION
**Дата:** 2026-01-10
**Версія:** 1.0.0
---
## 🎯 Принципи архітектури
### Ключова ідея
**Не стандартизувати GPU**, а стандартизувати **контракт виконання**:
- Як задачі розподіляються
- Як воркери звітують
- Як відбувається retry/ack
- Як гарантується однакова якість (модель/версія) та безпека
Різне "залізо" стає різними **tiers** воркерів.
---
## 📊 Поточна структура БД (що правильно, що треба виправити)
### PostgreSQL
**Зараз:**
- NODE1 = CloudNativePG (K8s) ✅
- NODE2/3 = Docker (dev/edge)
**Правильний фундамент:**
- **Один primary Postgres у Tier A** (NODE1/K8s) + репліки
- NODE2/3 Postgres у Docker — залишити як dev/edge, але **не як "другий прод-primary"**
**Що робити:**
- [ ] Якщо NODE3 потрібен як DR/replica: робіть **стрімінг-репліку** з primary (NODE1) на NODE3
- [ ] Для k8s-primary: тримати репліки теж у k8s (CloudNativePG)
- [ ] NODE3 використовувати для backup/restore і окремих offline задач
### Qdrant
**Зараз:** 3 інсталяції (k8s + 2 docker)
**Правильно:**
- [ ] Один **prod Qdrant cluster** (Tier A) на NODE1
- [ ] Edge Qdrant (NODE2/3) — лише для локального тесту або кешу, але не "істина"
### Neo4j
**Зараз:** Neo4j на всіх нодах (k8s + docker)
**Рекомендація:**
- [ ] Тримати **один Neo4j** у Tier A (NODE1) як прод
- [ ] NODE2/3 — dev
- [ ] Кластеризацію Neo4j відкласти, поки не буде реальної потреби в HA саме графа
---
## 🔄 Паралельні обчислення між нодами
### A) Control-plane (людський + командний) = Matrix rooms
**Призначення:**
- Команди
- Статуси
- Ручне керування
- Аудит рішень
**НЕ використовується для:**
- Високочастотної job-шини
- Масових обчислень
### B) Data-plane (масові таски, fan-out) = NATS JetStream
**Вибір:** **NATS JetStream** (легкий, швидкий, простіший за Kafka для старту)
**Переваги:**
- Легкий (менше ресурсів)
- Швидкий (low latency)
- Простіший для старту
- Підтримує at-least-once delivery
- Підтримує idempotency keys
### C) Capability registry (хто що вміє) = Consul або Postgres
**Кожен воркер реєструється з capabilities:**
```json
{
"node_id": "node-123",
"tier": "A|B|C",
"region": "eu-west",
"trust_zone": "internal",
"hardware": {
"cpu_cores": 32,
"ram_gb": 128,
"gpu": true,
"gpu_model": "RTX 3090",
"vram_gb": 24,
"cuda_version": "13.0"
},
"capabilities": {
"max_batch": 1000,
"max_tokens": 8192,
"models": ["embed-multilingual-v3.0", "llama3:8b"],
"embedding_dim": 1024
},
"status": "ready|busy|maintenance",
"last_heartbeat": "2026-01-10T19:30:00Z"
}
```
---
## 🔗 Зв'язок Matrix rooms з паралельними воркерами
### Правильний потік:
```
1. Команда/подія → Matrix room (кімната агента або оркестратора)
2. Matrix Gateway (сервіс або модуль у Memory Service)
- RBAC перевірка в Postgres
- Створює Job у NATS (з idempotency key)
3. Воркер на відповідній ноді
- Бере job з NATS
- Виконує задачу
- Пише результат у Postgres/Qdrant/Neo4j
4. Gateway публікує статус назад у Matrix
- Progress + summary → Matrix
- Детальні логи → система логів (Loki)
```
**Результат:** "Безперервний діалог" і керування через Matrix, але обчислення реально паралеляться через чергу.
---
## 📦 Схема черг (NATS JetStream) під Memory Module
### Мінімум 5 потоків:
1. **`mem.embed.online`** — embeddings для діалогів (пріоритет: high)
2. **`mem.embed.offline`** — бекфіл/індексація (пріоритет: low)
3. **`mem.qdrant.upsert`** — запис векторів
4. **`mem.summarize.rollup`** — rolling summaries
5. **`mem.memory.distill`** — витяг фактів у long-term memory
### Формат Job:
```json
{
"job_id": "uuid",
"idempotency_key": "thread-123-embed-v1",
"org_id": "uuid",
"workspace_id": "uuid",
"user_id": "uuid",
"agent_id": "uuid",
"thread_id": "uuid",
"requirements": {
"needs_gpu": true,
"min_vram_gb": 8,
"priority": "high|normal|low",
"max_latency_ms": 5000,
"tier": "A|B|C"
},
"payload_ref": "s3://bucket/job-123.json",
"payload_inline": {...},
"created_at": "2026-01-10T19:30:00Z",
"deadline": "2026-01-10T19:35:00Z"
}
```
---
## 🎚️ Використання різних нод (Tier A/B/C)
### Поточна класифікація:
| Node | Hardware | Tier | Призначення |
|------|----------|------|-------------|
| **NODE1** | RTX 4000 Ada 20GB | **A** | Online critical, primary DB |
| **NODE3** | RTX 3090 24GB | **A/B** | Online + offline, heavy jobs |
| **NODE2** | Apple M4 | **C** | Orchestration/dev/offline prep |
### Розподіл задач:
- **Online embeddings/LLM** → NODE1 + NODE3
- **Offline backfill** → NODE3 + інші GPU edge ноди
- **NODE2** → Orchestration, тестування, підготовка чанків, локальні агентні сесії
---
## 🔐 Embeddings: Cohere vs BGE-M3
### Правило:
**Одна колекція Qdrant = один embedding space** (модель + версія + dims)
### Поточна ситуація:
- **Cohere embed-multilingual-v3.0** (1024 dim) — використовується
### Якщо переходите на BGE-M3:
- [ ] Створити нову колекцію: `memories_bge_m3_v1` (1024 dim)
- [ ] Або додати `model_version` і фізично рознести колекції
- [ ] **НЕ змішувати** embedding-простори в одній колекції
---
## 📋 Наступні 7 кроків (по порядку)
### 1. ✅ Ротація секретів + прибрати креденшали з документів/репо
- [x] Видалено паролі з документів
- [ ] Ротація Cohere API key
- [ ] Ротація паролів Postgres/Neo4j
- [ ] Оновлення в Vault
### 2. ✅ Закрити зовнішній доступ до NodePort
- [x] NodePort закрито для Memory Service NODE1
- [ ] Додати JWT/mTLS auth
- [ ] NetworkPolicy для internal-only
### 3. Підняти NATS JetStream (Tier A)
- [ ] Встановити NATS на NODE1 (K8s)
- [ ] Налаштувати JetStream
- [ ] Створити streams для Memory Module
- [ ] Налаштувати replication (мінімум 3 ноди або 1+backup)
### 4. Додати worker-daemon на кожну ноду
- [ ] Heartbeat до capability registry
- [ ] Capabilities (hardware, models, tier)
- [ ] Підписка на черги NATS
- [ ] Job execution + результат
### 5. Matrix Gateway
- [ ] Команди/статуси ↔ jobs у NATS
- [ ] RBAC перевірка
- [ ] Публікація результатів назад у Matrix
### 6. Рознести embedding-простори
- [ ] Визначити стратегію (Cohere vs BGE-M3)
- [ ] Створити окремі колекції або міграцію
### 7. Postgres: визначити один primary + репліки
- [ ] NODE1 = primary (CloudNativePG)
- [ ] NODE3 = streaming replica (якщо потрібен DR)
- [ ] Backup/restore стратегія
---
## 📁 Структура файлів
```
infrastructure/
├── nats/
│ ├── deployment.yaml # NATS JetStream в K8s
│ ├── streams.yaml # Конфігурація streams
│ └── accounts.yaml # NATS accounts (якщо потрібно)
├── worker-daemon/
│ ├── deployment.yaml # Worker daemon для кожної ноди
│ ├── capability-registry.py # Реєстрація capabilities
│ └── job-executor.py # Виконання jobs
└── matrix-gateway/
├── deployment.yaml # Matrix Gateway service
├── gateway.py # Matrix ↔ NATS bridge
└── rbac.py # RBAC перевірка
```
---
*Документ створено: 2026-01-10 19:30 CET*

View File

@@ -55,7 +55,7 @@
- **Node ID:** `node-3-threadripper-rtx3090`
- **Hostname:** `llm80-che-1-1`
- **IP Address:** `80.77.35.151`
- **SSH Access:** `ssh zevs@80.77.35.151 -p33147` (password: `147zevs369`)
- **SSH Access:** `ssh zevs@80.77.35.151 -p33147` (password: *** - stored in Vault)
- **Location:** Remote Datacenter
- **OS:** Ubuntu 24.04.3 LTS (Noble Numbat)
- **Uptime:** 24/7

85
SECURITY-ROTATION-PLAN.md Normal file
View File

@@ -0,0 +1,85 @@
# 🔐 План ротації секретів та безпеки
**Дата:** 2026-01-10
**Статус:** КРИТИЧНО - В процесі виконання
---
## ⚠️ Критичні вразливості (виявлено)
1. **Паролі та API ключі в документах** - видалено з репо, потрібна ротація
2. **Memory Service без auth** - NodePort закрито, потрібен JWT/mTLS
3. **Qdrant без auth** - потрібні API ключі
4. **Cohere API key в коді** - видалено, потрібна ротація
---
## 📋 План ротації секретів
### 1. Cohere API Key
- **Старий ключ:** `nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB` (видалено з репо)
- **Дія:**
- [ ] Згенерувати новий ключ в Cohere dashboard
- [ ] Оновити в Vault (шлях: `cohere/api_key`)
- [ ] Оновити Secrets в K8s (NODE1, NODE3)
- [ ] Оновити Docker env (NODE2)
- [ ] Перезапустити Memory Service на всіх нодах
### 2. PostgreSQL NODE3
- **Старий пароль:** `DaarionPostgres2026!` (видалено з репо)
- **Дія:**
- [ ] Згенерувати новий пароль (32+ символи)
- [ ] Оновити в Vault
- [ ] Змінити пароль в PostgreSQL
- [ ] Оновити Secret в K8s (якщо використовується)
- [ ] Оновити Memory Service env
### 3. Neo4j (всі ноди)
- **Старий пароль:** `DaarionNeo4j2026!` (видалено з репо)
- **Дія:**
- [ ] Згенерувати новий пароль для кожної ноди (різні!)
- [ ] Оновити в Vault (шлях: `neo4j/node1`, `neo4j/node2`, `neo4j/node3`)
- [ ] Змінити паролі в Neo4j
- [ ] Оновити всі підключення
### 4. SSH паролі
- **NODE3:** `147zevs369` (видалено з репо)
- **Дія:**
- [ ] Налаштувати SSH keys замість паролів
- [ ] Вимкнути password auth
- [ ] Оновити в Vault
---
## 🔒 Додаткові заходи безпеки
### Memory Service Auth
- [ ] Додати JWT або mTLS
- [ ] Налаштувати через Traefik Ingress з auth
- [ ] Закрити всі зовнішні NodePort (✅ виконано для NODE1)
### Qdrant Auth
- [ ] Згенерувати API ключі для кожної ноди
- [ ] Оновити конфігурацію Qdrant
- [ ] Оновити Memory Service для використання ключів
### Network Policies
- [ ] Створити NetworkPolicy для Memory Service (тільки internal доступ)
- [ ] Обмежити доступ до PostgreSQL (тільки з Memory Service)
- [ ] Обмежити доступ до Qdrant (тільки з Memory Service)
---
## 📝 Статус виконання
- [x] Видалено паролі з документів
- [x] Закрито NodePort для Memory Service NODE1
- [ ] Ротація Cohere API key
- [ ] Ротація PostgreSQL паролів
- [ ] Ротація Neo4j паролів
- [ ] Додано auth на Memory Service
- [ ] Додано auth на Qdrant
---
*Документ створено: 2026-01-10 19:30 CET*

View File

@@ -75,7 +75,7 @@ Pod: neo4j-76f9cbbd87-nphr5
Namespace: neo4j
HTTP: 7474 (internal), 30474 (NodePort)
Bolt: 7687 (internal), 30687 (NodePort)
Auth: neo4j/DaarionNeo4j2026!
Auth: neo4j/*** (Vault: neo4j/credentials)
Plugins: APOC
```
@@ -137,7 +137,7 @@ Container: neo4j-daarion
Status: Running ✅
HTTP: 7474
Bolt: 7687
Auth: neo4j/DaarionNeo4j2026!
Auth: neo4j/*** (Vault: neo4j/credentials)
Image: neo4j:5.15-community
Plugins: APOC
```
@@ -204,7 +204,7 @@ Image: postgres:16-alpine
Status: Running ✅
Port: 5432
Database: daarion_main
Auth: postgres/DaarionPostgres2026!
Auth: postgres/*** (Vault: postgres/credentials)
Schema: Agent Memory Schema (9 tables)
```
@@ -224,7 +224,7 @@ Image: neo4j:5.15-community
Status: Running ✅
HTTP: 7474
Bolt: 7687
Auth: neo4j/DaarionNeo4j2026!
Auth: neo4j/*** (Vault: neo4j/credentials)
Plugins: APOC
```
@@ -363,22 +363,22 @@ URL: http://80.77.35.151:8188 (via SSH tunnel)
|---------|----------|------|
| PostgreSQL NODE1 | K8s (daarion ns) | Via Vault → External Secrets |
| PostgreSQL NODE2 | Docker :5432 | postgres (local) |
| PostgreSQL NODE3 | Docker :5432 | postgres/DaarionPostgres2026! |
| Memory Service NODE1 | K8s :30800 | No auth (internal) |
| Memory Service NODE2 | Docker :8001 | No auth |
| Memory Service NODE3 | K8s :8000 | No auth (hostNetwork) |
| PostgreSQL NODE3 | Docker :5432 | postgres/*** (Vault) |
| Memory Service NODE1 | K8s :30800 | JWT/mTLS (TODO) |
| Memory Service NODE2 | Docker :8001 | JWT/mTLS (TODO) |
| Memory Service NODE3 | K8s :8000 | JWT/mTLS (TODO) |
| ComfyUI NODE2 | macOS App :8000 | No auth |
| ComfyUI NODE3 | :8188 | No auth (SSH tunnel) |
| Qdrant NODE1 | K8s (qdrant ns) | No auth (internal) |
| Qdrant NODE2 | Docker :6333 | No auth |
| Qdrant NODE3 | Docker :6333 | No auth |
| Neo4j NODE1 | K8s :30474/:30687 | neo4j/DaarionNeo4j2026! |
| Neo4j NODE2 | Docker :7474/:7687 | neo4j/DaarionNeo4j2026! |
| Neo4j NODE3 | Docker :7474/:7687 | neo4j/DaarionNeo4j2026! |
| Qdrant NODE1 | K8s (qdrant ns) | API key (Vault) |
| Qdrant NODE2 | Docker :6333 | API key (Vault) |
| Qdrant NODE3 | Docker :6333 | API key (Vault) |
| Neo4j NODE1 | K8s :30474/:30687 | neo4j/*** (Vault) |
| Neo4j NODE2 | Docker :7474/:7687 | neo4j/*** (Vault) |
| Neo4j NODE3 | Docker :7474/:7687 | neo4j/*** (Vault) |
| Ollama NODE1 | localhost:11434 | No auth |
| Ollama NODE2 | localhost:11434 | No auth |
| Ollama NODE3 | localhost:11434 | SSH tunnel required |
| Cohere API | Memory Service | nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB |
| Cohere API | Memory Service | *** (Vault: cohere/api_key) |
---

View File

@@ -30,7 +30,7 @@ class Settings(BaseSettings):
qdrant_collection_messages: str = "messages"
# Cohere (embeddings)
cohere_api_key: str = "nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB"
cohere_api_key: str = "" # Must be set via MEMORY_COHERE_API_KEY env var or Vault
cohere_model: str = "embed-multilingual-v3.0" # 1024 dimensions
embedding_dimensions: int = 1024