## Agents Added - Alateya: R&D, biotech, innovations - Clan (Spirit): Community spirit agent - Eonarch: Consciousness evolution agent ## Changes - docker-compose.node1.yml: Added tokens for all 3 new agents - gateway-bot/http_api.py: Added configs and webhook endpoints - gateway-bot/clan_prompt.txt: New prompt file - gateway-bot/eonarch_prompt.txt: New prompt file ## Fixes - Fixed ROUTER_URL from :9102 to :8000 (internal container port) - All 9 Telegram agents now working ## Documentation - Created PROJECT-MASTER-INDEX.md - single entry point - Added various status documents and scripts Tokens configured: - Helion, NUTRA, Agromatrix (existing) - Alateya, Clan, Eonarch (new) - Druid, GreenFood, DAARWIZZ (configured)
521 lines
14 KiB
Markdown
521 lines
14 KiB
Markdown
# 🗄️ Database & Persistence Audit — NODA1 & NODA2
|
||
|
||
**Date:** 2026-01-22
|
||
**Purpose:** Повний аудит конфігурації БД, агентів та persistent storage
|
||
**Goal:** Запобігти втраті даних при rebuild контейнерів
|
||
|
||
---
|
||
|
||
## 🔍 Проблема
|
||
|
||
> "Агенти працюють нормально, але ми вже вдруге налаштовуємо базу даних"
|
||
|
||
**Symptoms:**
|
||
- Дані зникають після rebuild контейнерів
|
||
- Потрібно повторно налаштовувати БД
|
||
- Collections в Qdrant порожні
|
||
|
||
---
|
||
|
||
## ✅ Що працює ПРАВИЛЬНО
|
||
|
||
### 1. Docker Volumes налаштовані
|
||
|
||
#### NODA1 (`docker-compose.node1.yml`)
|
||
```yaml
|
||
volumes:
|
||
qdrant-data-node1: ✅ 20KB (порожній)
|
||
neo4j-data-node1: ✅ Є
|
||
postgres_data_node1: ✅ 81MB (АКТИВНИЙ)
|
||
redis-data-node1: ✅ Є
|
||
minio-data-node1: ✅ Є
|
||
nats-data-node1: ✅ Є
|
||
# ... інші volumes
|
||
```
|
||
|
||
**Поточний стан:**
|
||
- ✅ Volumes створені
|
||
- ✅ PostgreSQL має 81MB даних
|
||
- ✅ Дані зберігаються в `/var/lib/docker/volumes/`
|
||
|
||
---
|
||
|
||
### 2. Агенти налаштовані
|
||
|
||
**7 активних Telegram ботів:**
|
||
1. DAARWIZZ (`agent_id="daarwizz"`)
|
||
2. Helion (`agent_id="helion"`)
|
||
3. GREENFOOD (`agent_id="greenfood"`)
|
||
4. AgroMatrix (`agent_id="agromatrix"`)
|
||
5. NUTRA (`agent_id="nutra"`)
|
||
6. Druid (`agent_id="druid"`)
|
||
7. Alateya (`agent_id="alateya"`) - без токену
|
||
|
||
**Конфігурації:**
|
||
- Файл: `gateway-bot/http_api.py`
|
||
- Кожен має унікальний `agent_id`
|
||
- Кожен має окремий prompt файл
|
||
|
||
---
|
||
|
||
### 3. PostgreSQL працює
|
||
|
||
**Бази даних:**
|
||
```sql
|
||
daarion_main -- Artifacts (3 таблиці)
|
||
daarion_memory -- user_facts (з agent_id полем!)
|
||
rag -- RAG сервіс
|
||
postgres -- System DB
|
||
```
|
||
|
||
**user_facts structure:**
|
||
```sql
|
||
Columns:
|
||
- agent_id TEXT (з індексом!)
|
||
- user_id TEXT
|
||
- team_id TEXT
|
||
- fact_key TEXT
|
||
- fact_value TEXT
|
||
- fact_value_json JSONB
|
||
|
||
Unique constraint:
|
||
(user_id, team_id, agent_id, fact_key)
|
||
```
|
||
|
||
**Реальні дані (станом на 2026-01-22):**
|
||
- `nutra` - 3 записи
|
||
- `agromatrix` - 2 записи
|
||
- Деякі без `agent_id` (глобальні profiles)
|
||
|
||
✅ **PostgreSQL зберігає дані правильно!**
|
||
|
||
---
|
||
|
||
## ⚠️ Проблеми та їх причини
|
||
|
||
### 1. Qdrant Collections порожні
|
||
|
||
**Факт:**
|
||
```bash
|
||
curl http://localhost:6333/collections
|
||
# Result: {"collections": []}
|
||
```
|
||
|
||
**Причина:**
|
||
- Volume існує: `qdrant-data-node1` (20KB - тільки metadata)
|
||
- Router ще не створив collections
|
||
- Або collections створені, але volume був очищений
|
||
|
||
**Як має бути:**
|
||
Router динамічно створює collections:
|
||
- `{agent_id}_messages`
|
||
- `{agent_id}_memory_items`
|
||
- `{agent_id}_docs`
|
||
|
||
Приклад: `agromatrix_messages`, `greenfood_messages`, тощо
|
||
|
||
---
|
||
|
||
### 2. Volume naming мismatch
|
||
|
||
**Виявлено дублювання:**
|
||
```
|
||
postgres_data_node1 81MB (СТАРИЙ)
|
||
microdao-daarion_postgres_data_node1 81MB (АКТИВНИЙ)
|
||
```
|
||
|
||
**Активний:** `microdao-daarion_postgres_data_node1`
|
||
|
||
**Проблема:**
|
||
- Docker Compose автоматично додає prefix `microdao-daarion_`
|
||
- В `docker-compose.node1.yml` вказано просто `postgres_data_node1`
|
||
- Docker створює `{project}_postgres_data_node1`
|
||
|
||
---
|
||
|
||
### 3. Відсутність backup стратегії
|
||
|
||
**Поточний стан:**
|
||
- ❌ Немає автоматичних backups PostgreSQL
|
||
- ❌ Немає backups Qdrant
|
||
- ❌ Немає backups Neo4j
|
||
- ✅ Є cron backup (3 AM) на host рівні
|
||
|
||
**З документації (`docker-compose.db.yml`):**
|
||
```yaml
|
||
db-backup:
|
||
image: prodrigestivill/postgres-backup-local:latest
|
||
environment:
|
||
SCHEDULE: "@every 12h"
|
||
BACKUP_KEEP_DAYS: 7
|
||
BACKUP_KEEP_WEEKS: 4
|
||
BACKUP_KEEP_MONTHS: 6
|
||
volumes:
|
||
- ./db_backups:/backups
|
||
```
|
||
|
||
⚠️ **Цей сервіс НЕ запущений на NОДА1!**
|
||
|
||
---
|
||
|
||
## 🎯 Чому дані "зникають"
|
||
|
||
### Сценарій 1: Rebuild контейнера БЕЗ volumes
|
||
```bash
|
||
# НЕБЕЗПЕЧНО!
|
||
docker rm -f dagi-postgres
|
||
docker run ... postgres:16 # Без -v
|
||
|
||
# Результат: Новий контейнер з порожньою БД
|
||
```
|
||
|
||
### Сценарій 2: Очищення volumes
|
||
```bash
|
||
# ДУЖЕ НЕБЕЗПЕЧНО!
|
||
docker volume rm qdrant-data-node1
|
||
|
||
# Результат: Всі дані Qdrant втрачені назавжди
|
||
```
|
||
|
||
### Сценарій 3: Неправильний COMPOSE_PROJECT_NAME
|
||
```bash
|
||
# Якщо змінюється project name:
|
||
COMPOSE_PROJECT_NAME=dagi_node1 docker compose up
|
||
# vs
|
||
COMPOSE_PROJECT_NAME=microdao-daarion docker compose up
|
||
|
||
# Docker створює РІЗНІ volumes!
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 Рекомендації (КРИТИЧНО)
|
||
|
||
### 1. Зафіксувати volume names
|
||
|
||
**Оновити `docker-compose.node1.yml`:**
|
||
```yaml
|
||
volumes:
|
||
qdrant-data-node1:
|
||
name: qdrant-data-node1 # EXPLICIT NAME
|
||
driver: local
|
||
|
||
postgres_data_node1:
|
||
name: postgres-data-node1 # EXPLICIT NAME
|
||
driver: local
|
||
|
||
neo4j-data-node1:
|
||
name: neo4j-data-node1
|
||
driver: local
|
||
```
|
||
|
||
**Чому:** Запобігає створенню volumes з prefix-ами
|
||
|
||
---
|
||
|
||
### 2. Додати автоматичні backups
|
||
|
||
**Створити `docker-compose.backups.yml`:**
|
||
```yaml
|
||
version: "3.9"
|
||
|
||
services:
|
||
postgres-backup:
|
||
image: prodrigestivill/postgres-backup-local:15
|
||
container_name: postgres-backup-node1
|
||
restart: unless-stopped
|
||
environment:
|
||
POSTGRES_HOST: dagi-postgres
|
||
POSTGRES_DB: daarion_main,daarion_memory,rag
|
||
POSTGRES_USER: daarion
|
||
POSTGRES_PASSWORD: DaarionDB2026!
|
||
SCHEDULE: "@every 6h"
|
||
BACKUP_KEEP_DAYS: 7
|
||
BACKUP_KEEP_WEEKS: 4
|
||
BACKUP_KEEP_MONTHS: 6
|
||
POSTGRES_EXTRA_OPTS: "-Z9 --schema=public --blobs"
|
||
volumes:
|
||
- /opt/backups/postgres:/backups
|
||
networks:
|
||
- dagi-network
|
||
|
||
qdrant-backup:
|
||
image: qdrant/qdrant:latest
|
||
container_name: qdrant-backup-node1
|
||
restart: "no"
|
||
environment:
|
||
SCHEDULE: "@daily"
|
||
volumes:
|
||
- qdrant-data-node1:/qdrant/storage:ro
|
||
- /opt/backups/qdrant:/backups
|
||
command: >
|
||
sh -c "
|
||
tar czf /backups/qdrant-$(date +%Y%m%d-%H%M%S).tar.gz /qdrant/storage &&
|
||
find /backups -name 'qdrant-*.tar.gz' -mtime +30 -delete
|
||
"
|
||
networks:
|
||
- dagi-network
|
||
|
||
networks:
|
||
dagi-network:
|
||
external: true
|
||
|
||
volumes:
|
||
qdrant-data-node1:
|
||
external: true
|
||
name: qdrant-data-node1
|
||
```
|
||
|
||
**Запуск:**
|
||
```bash
|
||
docker compose -f docker-compose.backups.yml up -d postgres-backup
|
||
```
|
||
|
||
---
|
||
|
||
### 3. Створити restore процедури
|
||
|
||
**Файл: `scripts/restore-from-backup.sh`**
|
||
```bash
|
||
#!/bin/bash
|
||
# Restore PostgreSQL from backup
|
||
|
||
BACKUP_FILE="$1"
|
||
DATABASE="${2:-daarion_memory}"
|
||
|
||
if [ -z "$BACKUP_FILE" ]; then
|
||
echo "Usage: $0 <backup_file> [database]"
|
||
echo "Example: $0 /opt/backups/postgres/daarion_memory-20260122-030000.sql.gz"
|
||
exit 1
|
||
fi
|
||
|
||
echo "Restoring $DATABASE from $BACKUP_FILE..."
|
||
|
||
# Stop services that use this DB
|
||
docker compose -f docker-compose.node1.yml stop dagi-memory-service-node1 dagi-router-node1
|
||
|
||
# Restore
|
||
gunzip -c "$BACKUP_FILE" | docker exec -i dagi-postgres psql -U daarion -d "$DATABASE"
|
||
|
||
# Restart services
|
||
docker compose -f docker-compose.node1.yml start dagi-memory-service-node1 dagi-router-node1
|
||
|
||
echo "✅ Restore complete!"
|
||
```
|
||
|
||
---
|
||
|
||
### 4. Додати pre-rebuild checks
|
||
|
||
**Файл: `scripts/safe-rebuild.sh`**
|
||
```bash
|
||
#!/bin/bash
|
||
# Safe container rebuild with backup verification
|
||
|
||
SERVICE="$1"
|
||
|
||
if [ -z "$SERVICE" ]; then
|
||
echo "Usage: $0 <service_name>"
|
||
exit 1
|
||
fi
|
||
|
||
echo "🔍 Pre-rebuild checks for $SERVICE..."
|
||
|
||
# 1. Check volumes
|
||
echo "📦 Checking volumes..."
|
||
docker inspect "$SERVICE" | grep -A20 "Mounts"
|
||
|
||
# 2. Backup first
|
||
echo "💾 Creating backup..."
|
||
case "$SERVICE" in
|
||
dagi-postgres)
|
||
docker exec dagi-postgres pg_dumpall -U daarion | gzip > "/opt/backups/manual/postgres-$(date +%Y%m%d-%H%M%S).sql.gz"
|
||
;;
|
||
dagi-qdrant-node1)
|
||
tar czf "/opt/backups/manual/qdrant-$(date +%Y%m%d-%H%M%S).tar.gz" /var/lib/docker/volumes/qdrant-data-node1/_data
|
||
;;
|
||
esac
|
||
|
||
# 3. Confirm
|
||
read -p "⚠️ Proceed with rebuild? (yes/no): " CONFIRM
|
||
if [ "$CONFIRM" != "yes" ]; then
|
||
echo "❌ Aborted"
|
||
exit 0
|
||
fi
|
||
|
||
# 4. Rebuild
|
||
echo "🔨 Rebuilding $SERVICE..."
|
||
docker compose -f docker-compose.node1.yml up -d --build --force-recreate "$SERVICE"
|
||
|
||
echo "✅ Rebuild complete!"
|
||
```
|
||
|
||
---
|
||
|
||
### 5. Документувати volume layout
|
||
|
||
**Створити `VOLUMES-LAYOUT.md`:**
|
||
```markdown
|
||
# Docker Volumes Layout — NODA1
|
||
|
||
## PostgreSQL
|
||
Volume: `postgres-data-node1` (або `microdao-daarion_postgres_data_node1`)
|
||
Path: `/var/lib/docker/volumes/postgres-data-node1/_data`
|
||
Size: ~81MB
|
||
Databases: daarion_main, daarion_memory, rag
|
||
Backup: Every 6h → /opt/backups/postgres/
|
||
|
||
## Qdrant
|
||
Volume: `qdrant-data-node1`
|
||
Path: `/var/lib/docker/volumes/qdrant-data-node1/_data`
|
||
Size: ~20KB (пусто після rebuild!)
|
||
Collections: {agent_id}_messages, {agent_id}_memory_items, {agent_id}_docs
|
||
Backup: Daily → /opt/backups/qdrant/
|
||
|
||
## Neo4j
|
||
Volume: `neo4j-data-node1`, `neo4j-logs-node1`
|
||
Path: `/var/lib/docker/volumes/neo4j-data-node1/_data`
|
||
Backup: Manual (cypher-shell DUMP)
|
||
|
||
## Redis
|
||
Volume: `redis-data-node1`
|
||
Path: `/var/lib/docker/volumes/redis-data-node1/_data`
|
||
Backup: RDB snapshots every 1h
|
||
|
||
## MinIO
|
||
Volume: `minio-data-node1`
|
||
Path: `/var/lib/docker/volumes/minio-data-node1/_data`
|
||
Purpose: Artifacts, images, files
|
||
Backup: S3 sync to external storage
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 Action Plan (Терміново)
|
||
|
||
### Крок 1: Backup ЗАРАЗ
|
||
```bash
|
||
# На НОДА1
|
||
ssh root@144.76.224.179
|
||
|
||
# PostgreSQL
|
||
docker exec dagi-postgres pg_dumpall -U daarion | gzip > /root/postgres-emergency-$(date +%Y%m%d-%H%M%S).sql.gz
|
||
|
||
# Qdrant
|
||
tar czf /root/qdrant-emergency-$(date +%Y%m%d-%H%M%S).tar.gz /var/lib/docker/volumes/qdrant-data-node1/_data
|
||
|
||
# Neo4j
|
||
tar czf /root/neo4j-emergency-$(date +%Y%m%d-%H%M%S).tar.gz /var/lib/docker/volumes/neo4j-data-node1/_data
|
||
|
||
ls -lh /root/*emergency*.tar.gz
|
||
```
|
||
|
||
### Крок 2: Зафіксувати volume names
|
||
```bash
|
||
# На НОДА1
|
||
cd /opt/microdao-daarion
|
||
cp docker-compose.node1.yml docker-compose.node1.yml.backup-$(date +%Y%m%d)
|
||
|
||
# Редагувати volumes секцію (додати explicit names)
|
||
nano docker-compose.node1.yml
|
||
|
||
# Рестарт з новими іменами
|
||
docker compose -f docker-compose.node1.yml up -d
|
||
```
|
||
|
||
### Крок 3: Налаштувати автоматичні backups
|
||
```bash
|
||
# Створити директорії
|
||
mkdir -p /opt/backups/{postgres,qdrant,neo4j,manual}
|
||
|
||
# Створити docker-compose.backups.yml
|
||
nano docker-compose.backups.yml
|
||
|
||
# Запустити
|
||
docker compose -f docker-compose.backups.yml up -d
|
||
```
|
||
|
||
### Крок 4: Створити restore scripts
|
||
```bash
|
||
mkdir -p /opt/scripts
|
||
nano /opt/scripts/restore-from-backup.sh
|
||
chmod +x /opt/scripts/restore-from-backup.sh
|
||
|
||
nano /opt/scripts/safe-rebuild.sh
|
||
chmod +x /opt/scripts/safe-rebuild.sh
|
||
```
|
||
|
||
### Крок 5: Протестувати backup/restore
|
||
```bash
|
||
# Test backup
|
||
docker exec postgres-backup-node1 sh -c "/backup.sh"
|
||
ls -lh /opt/backups/postgres/
|
||
|
||
# Test restore (на staging БД)
|
||
# НЕ на production!
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 Safety Rules (ЗАВЖДИ дотримуватись)
|
||
|
||
### НІКОЛИ не робити:
|
||
```bash
|
||
❌ docker volume rm <volume-name>
|
||
❌ docker compose down -v
|
||
❌ docker system prune -a --volumes
|
||
❌ rm -rf /var/lib/docker/volumes/<volume>
|
||
```
|
||
|
||
### ЗАВЖДИ робити:
|
||
```bash
|
||
✅ Backup ПЕРЕД rebuild
|
||
✅ Перевірити volumes ПЕРЕД видаленням контейнера
|
||
✅ Використовувати explicit volume names
|
||
✅ Тестувати restore процедури
|
||
✅ Зберігати backups поза сервером
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Поточний стан volumes
|
||
|
||
```bash
|
||
# NОДА1 volumes (станом на 2026-01-22)
|
||
postgres_data_node1: 81MB ✅ АКТИВНИЙ, є дані
|
||
microdao-daarion_postgres_data_node1: 81MB ✅ АКТИВНИЙ (те саме)
|
||
qdrant-data-node1: 20KB ⚠️ ПОРОЖНІЙ
|
||
microdao-daarion_qdrant-data-node1: 20KB ⚠️ ПОРОЖНІЙ
|
||
neo4j-data-node1: ??? ✅ Є
|
||
redis-data-node1: ??? ✅ Є
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Висновок
|
||
|
||
### Що працює:
|
||
✅ Docker volumes налаштовані
|
||
✅ PostgreSQL зберігає дані (81MB)
|
||
✅ Агенти працюють з правильними agent_id
|
||
✅ Ізоляція пам'яті між агентами правильна
|
||
|
||
### Що потрібно:
|
||
⚠️ Зафіксувати volume names (explicit)
|
||
⚠️ Налаштувати автоматичні backups
|
||
⚠️ Створити restore процедури
|
||
⚠️ Протестувати backup/restore
|
||
⚠️ Документувати процедури
|
||
|
||
### Чому "знову налаштовуємо":
|
||
❌ Qdrant контейнер пересоздавали без збереження даних
|
||
❌ Collections не створилися автоматично після rebuild
|
||
❌ Немає backup стратегії
|
||
❌ Немає документації про restore
|
||
|
||
---
|
||
|
||
**Next Steps:** Виконати Action Plan (5 кроків)
|
||
**Priority:** КРИТИЧНО - створити backups ЗАРАЗ
|
||
**Документація:** Оновити INFRASTRUCTURE.md з процедурами backup/restore
|