# 🚨 NODE1 Recovery & Safety Runbook **Version:** 1.0 **Last Updated:** 2026-01-26 **Target:** НОДА1 Production (144.76.224.179) --- ## 0. Golden Signals (що вважаємо нормою) ### Health Endpoints (HTTP 200) | Сервіс | Порт | Endpoint | Container | |--------|------|----------|-----------| | Router | 9102 | `/health` | dagi-router-node1 | | Gateway | 9300 | `/health` | dagi-gateway | | Memory Service | 8000 | `/health` | dagi-memory-service-node1 | | RAG Service | 9500 | `/health` | rag-service-node1 | | Swapper | 8890 | `/health` | swapper-service-node1 | | Qdrant | 6333 | `/healthz` | dagi-qdrant-node1 | | Vision Encoder | 8001 | `/health` | dagi-vision-encoder-node1 | | Parser Pipeline | 8101 | `/health` | parser-pipeline | | Prometheus | 9090 | `/-/healthy` | prometheus | | Grafana | 3030 | `/api/health` | grafana | ### By Design (норма — не є проблемою) | Сервіс | Порт | Статус | Причина | |--------|------|--------|---------| | RBAC | 9200 | Internal only | Порт не опублікований, доступ через docker network | | Image-gen | 8892 | Не запущено | Використовується swapper-service замість | | Parser | 9400 | Відсутній | Замінено на parser-pipeline:8101 | --- ## 1. Тріаж за 2 хвилини ### 1.1 Підключення до НОДА1 ```bash ssh root@144.76.224.179 cd /opt/microdao-daarion ``` ### 1.2 Статус контейнерів ```bash docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | head -30 ``` ### 1.3 Швидкий health check всіх сервісів ```bash echo "=== HEALTH CHECK ===" && \ curl -sS -m 3 -o /dev/null -w "Router 9102: %{http_code}\n" http://127.0.0.1:9102/health && \ curl -sS -m 3 -o /dev/null -w "Gateway 9300: %{http_code}\n" http://127.0.0.1:9300/health && \ curl -sS -m 3 -o /dev/null -w "Memory 8000: %{http_code}\n" http://127.0.0.1:8000/health && \ curl -sS -m 3 -o /dev/null -w "RAG 9500: %{http_code}\n" http://127.0.0.1:9500/health && \ curl -sS -m 3 -o /dev/null -w "Swapper 8890: %{http_code}\n" http://127.0.0.1:8890/health && \ curl -sS -m 3 -o /dev/null -w "Qdrant 6333: %{http_code}\n" http://127.0.0.1:6333/healthz && \ curl -sS -m 3 -o /dev/null -w "Vision 8001: %{http_code}\n" http://127.0.0.1:8001/health && \ curl -sS -m 3 -o /dev/null -w "Parser 8101: %{http_code}\n" http://127.0.0.1:8101/health && \ curl -sS -m 3 -o /dev/null -w "Prometheus 9090: %{http_code}\n" http://127.0.0.1:9090/-/healthy && \ curl -sS -m 3 -o /dev/null -w "Grafana 3030: %{http_code}\n" http://127.0.0.1:3030/api/health ``` ### 1.4 Логи ключових сервісів ```bash # Router docker logs dagi-router-node1 --tail 50 # Gateway docker logs dagi-gateway --tail 50 # Memory Service docker logs dagi-memory-service-node1 --tail 50 # Qdrant docker logs dagi-qdrant-node1 --tail 50 ``` --- ## 2. Плейбуки відновлення ### A) Memory Service не може підключитися до Qdrant **Симптоми:** - Memory health → 500 - Логи: "Temporary failure in name resolution" або "connection refused" **Діагностика:** ```bash # Перевірити env docker exec dagi-memory-service-node1 env | grep -E "QDRANT" # Перевірити DNS resolution docker exec dagi-memory-service-node1 python3 -c "import socket; print(socket.gethostbyname('dagi-qdrant-node1'))" ``` **Фікс:** ```bash # 1. Зупинити і видалити контейнер docker stop dagi-memory-service-node1 docker rm dagi-memory-service-node1 # 2. Запустити з правильним QDRANT_HOST docker run -d \ --name dagi-memory-service-node1 \ --network dagi-network \ --network-alias memory-service \ -p 8000:8000 \ -e MEMORY_POSTGRES_HOST=dagi-postgres \ -e MEMORY_POSTGRES_PORT=5432 \ -e MEMORY_POSTGRES_USER=daarion \ -e MEMORY_POSTGRES_PASSWORD=DaarionDB2026! \ -e MEMORY_POSTGRES_DB=daarion_memory \ -e MEMORY_QDRANT_HOST=dagi-qdrant-node1 \ -e MEMORY_QDRANT_PORT=6333 \ -e MEMORY_DEBUG=false \ -e MEMORY_COHERE_API_KEY=nOdOXnuepLku2ipJWpe6acWgAsJCsDhMO0RnaEJB \ --restart unless-stopped \ microdao-daarion-memory-service:latest # 3. Перевірити sleep 5 && curl -sS http://127.0.0.1:8000/health ``` ### B) Qdrant повільний/падає (диск/пам'ять) **Симптоми:** latency, OOM-kill, 5xx **Діагностика:** ```bash # Логи docker logs dagi-qdrant-node1 --tail 100 # Ресурси df -h free -m docker stats --no-stream | grep qdrant ``` **Якщо диск майже повний:** ```bash # Очистити старі логи find /var/log -name "*.log" -mtime +7 -delete # Список снапшотів Qdrant curl -s http://localhost:6333/snapshots # Видалити старі снапшоти (обережно!) # curl -X DELETE "http://localhost:6333/snapshots/" # Перезапустити Qdrant docker restart dagi-qdrant-node1 ``` ### C) Parser Pipeline не обробляє jobs **Симптоми:** черга не рухається, RAG не наповнюється **Діагностика:** ```bash docker logs parser-pipeline --tail 100 curl -sS http://127.0.0.1:8101/health ``` **Фікс:** ```bash docker restart parser-pipeline sleep 5 && curl -sS http://127.0.0.1:8101/health ``` ### D) Grafana/Prometheus не працює **Діагностика:** ```bash curl -sS http://127.0.0.1:9090/-/healthy curl -sS http://127.0.0.1:3030/api/health docker logs prometheus --tail 50 docker logs grafana --tail 50 ``` **Фікс:** ```bash docker restart prometheus grafana ``` ### E) Gateway не приймає webhook-и **Симптоми:** Telegram боти не відповідають **Діагностика:** ```bash docker logs dagi-gateway --tail 100 | grep -E "error|webhook|telegram" curl -sS http://127.0.0.1:9300/health ``` **Фікс:** ```bash docker restart dagi-gateway sleep 5 && curl -sS http://127.0.0.1:9300/health ``` --- ## 3. Безпечний стандартний рестарт **Порядок (від edge до core):** ```bash # 1. Edge services docker restart dagi-router-node1 dagi-gateway # 2. Core services docker restart rag-service-node1 dagi-memory-service-node1 swapper-service-node1 # 3. Processing pipelines docker restart dagi-vision-encoder-node1 parser-pipeline # 4. Observability (в кінці) docker restart prometheus grafana # 5. Verify all sleep 10 && curl -sS http://127.0.0.1:9102/health && echo " Router OK" ``` **НЕ ЧІПАТИ БЕЗ ПОТРЕБИ:** - `dagi-qdrant-node1` — vector DB з даними - `dagi-postgres` — PostgreSQL з даними - `dagi-neo4j-node1` — Graph DB з даними --- ## 4. Backup / Rollback ### Перед ризиковими змінами ```bash # 1. Qdrant snapshot curl -X POST "http://localhost:6333/snapshots" # 2. Compose backup cp docker-compose.node1.yml docker-compose.node1.yml.backup.$(date +%Y%m%d_%H%M%S) # 3. Перевірити PostgreSQL бекапи ls -la /opt/backups/postgres/ ``` ### Відкат compose ```bash # Знайти останній бекап ls -la docker-compose.node1.yml.backup.* # Відкотити cp docker-compose.node1.yml.backup. docker-compose.node1.yml docker compose -f docker-compose.node1.yml up -d ``` ### Відкат Qdrant (restore drill) ```bash # 1. Список снапшотів curl -s http://localhost:6333/snapshots # 2. Відновлення (на тестовому інстансі спочатку!) # УВАГА: це перезапише всі дані! # curl -X POST "http://localhost:6333/snapshots/recover" \ # -H "Content-Type: application/json" \ # -d '{"location": "file:///qdrant/snapshots/"}' ``` --- ## 5. Інцидентний протокол ### При виникненні проблеми: 1. **Зафіксувати** час + симптом 2. **Тріаж** (Section 1) — локалізувати проблему 3. **Backup** перед змінами (якщо торкаємось даних) 4. **Мінімальна дія** → перевірка health 5. **Задокументувати** в `NODA1-CURRENT-STATUS-YYYY-MM-DD.md`: - Причина - Що змінив - Як перевіряв - Що зробити щоб не повторилось ### Ескалація - **Level 1:** Перезапуск сервісу - **Level 2:** Перевірка логів, DNS, мережі - **Level 3:** Відкат до backup - **Level 4:** Повний rebuild з останнього golden snapshot --- ## 6. Контакти та ресурси - **SSH:** `ssh root@144.76.224.179` - **Grafana:** http://144.76.224.179:3030 - **Prometheus:** http://144.76.224.179:9090 - **Qdrant Dashboard:** http://144.76.224.179:6333/dashboard ### Документація - `NODA1-README.md` — головний README - `INFRASTRUCTURE.md` — повна інфраструктура - `NODA1-CURRENT-STATUS-*.md` — поточний статус --- --- ## 7. Rate Limit / Proxy Recovery ### Архітектура захисту (після hardening) ``` Internet → [UFW] → Nginx:80/443 → Gateway:9300 (localhost) ↓ [Rate Limit: 10 req/s] ↓ [iptables DOCKER-USER] ↓ Internal services (blocked from outside) ``` ### Якщо Nginx не працює ```bash # Перевірка статусу systemctl status nginx # Перегляд логів tail -50 /var/log/nginx/error.log # Перезапуск systemctl restart nginx # Якщо config broken nginx -t # Відновити з backup cp /etc/nginx/conf.d/node1-api.conf.backup /etc/nginx/conf.d/node1-api.conf nginx -t && systemctl reload nginx ``` ### Якщо треба тимчасово відкрити порт (для діагностики) ```bash # Тимчасово видалити блокування для порту 9300 iptables -D DOCKER-USER -p tcp --dport 9300 ! -s 127.0.0.1 -j DROP # Повернути блокування iptables -I DOCKER-USER -p tcp --dport 9300 ! -s 127.0.0.1 -j DROP ``` ### Якщо rate limit занадто strict ```bash # Змінити ліміт в nginx vim /etc/nginx/conf.d/node1-api.conf # Знайти: rate=10r/s → rate=20r/s # Знайти: burst=20 → burst=40 nginx -t && systemctl reload nginx ``` ### Відновити iptables після reboot ```bash # Якщо правила зникли після reboot iptables-restore < /etc/iptables.rules # Перевірка iptables -L DOCKER-USER -n | grep DROP ``` ### Доступ до Grafana/Prometheus (через SSH tunnel) ```bash # З вашого ноутбука: ssh -L 3030:localhost:3030 -L 9090:localhost:9090 root@144.76.224.179 # Потім в браузері: # Grafana: http://localhost:3030 # Prometheus: http://localhost:9090 ``` --- ## 8. Конфігураційні файли | Файл | Призначення | |------|-------------| | `/etc/nginx/conf.d/node1-api.conf` | Nginx proxy + rate limit | | `/etc/iptables.rules` | Firewall rules backup | | `/opt/microdao-daarion/ops/status.sh` | Health check script | | `/opt/microdao-daarion/ops/hardening/apply-node1-firewall.sh` | UFW hardening script | | `/opt/microdao-daarion/monitoring/prometheus/rules/node1.rules.yml` | Alerting rules | --- **Maintained by:** DAARION Team **Last Review:** 2026-01-26