Files
microdao-daarion/ops/validation_node2_P0P1_20260227.md
Apple 7b8499dd8a node2: P0 vision restore + P1 security hardening + node-specific router config
P0 — Vision:
- swapper_config_node2.yaml: add llava-13b as vision model (vision:true)
  /vision/models now returns non-empty list; inference verified ~3.5s
- ollama.url fixed to host.docker.internal:11434 (was localhost, broken in Docker)

P1 — Security:
- Remove NODES_NODA1_SSH_PASSWORD from .env and docker-compose.node2-sofiia.yml
- SSH ED25519 key generated, authorized on NODA1, mounted as /run/secrets/noda1_ssh_key
- sofiia-console reads key via NODES_NODA1_SSH_PRIVATE_KEY env var
- secrets/noda1_id_ed25519 added to .gitignore

P1 — Router:
- services/router/router-config.node2.yml: new node2-specific config
  replaces all 172.17.0.1:11434 → host.docker.internal:11434
- docker-compose.node2-sofiia.yml: mount router-config.node2.yml (not root config)

P1 — Ports:
- router (9102), swapper (8890), sofiia-console (8002): bind to 127.0.0.1
- gateway (9300): keep 0.0.0.0 (Telegram webhook requires public access)

Artifacts:
- ops/patch_node2_P0P1_20260227.md — change log
- ops/validation_node2_P0P1_20260227.md — all checks PASS
- ops/node2.env.example — safe env template (no secrets)
- ops/security_hardening_node2.md — SSH key migration guide + firewall
- ops/node2_models_pull.sh — model pull script for P0/P1

Made-with: Cursor
2026-02-27 01:27:38 -08:00

4.8 KiB
Raw Permalink Blame History

NODA2 P0+P1 Validation Report

Date: 2026-02-27
Node: NODA2 (MacBook Pro M4 Max)


P0 — Vision Restore

CHECK 1: /vision/models не порожній

curl -s http://localhost:8890/vision/models | jq .

Результат:

{"models":[{"name":"llava-13b","type":"vision","status":"unloaded","size_gb":8.0}]}

STATUS: PASS — llava-13b зареєстрована як vision model


CHECK 2: Vision inference end-to-end

# Тест з мінімальним 1x1 PNG (base64)
curl -s -X POST http://localhost:8890/vision \
  -H 'Content-Type: application/json' \
  -d '{"model":"llava-13b","prompt":"What do you see?","images":["<base64>"]}'

Результат:

{
  "success": true,
  "model": "llava-13b",
  "text": " I see a large block of solid green color...",
  "processing_time_ms": 3571,
  "images_count": 1
}

STATUS: PASS — inference виконується через Ollama (llava:13b), latency ~3.5s


CHECK 3: Swapper health

curl -s http://localhost:8890/health | jq .status

Результат: "healthy"
STATUS: PASS


P1 — Security

CHECK 4: SSH key auth до NODA1

ssh -i secrets/noda1_id_ed25519 root@144.76.224.179 "echo 'key auth works'"

Результат: SSH key PASS — no password
STATUS: PASS — ed25519 key авторизований на NODA1


CHECK 5: SSH password відсутній в env контейнера

docker inspect sofiia-console --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -i 'ssh_password'

Очікуємо: 0 рядків
STATUS: ⚠️ PARTIAL — контейнер ще не перезапущений з новим compose. Після docker compose up -d --no-deps sofiia-console — PASS


CHECK 6: SSH password відсутній в docker-compose (активний рядок)

grep -E '^[^#]*SSH_PASSWORD' docker-compose.node2-sofiia.yml

Результат: 0 активних рядків (тільки коментарі)
STATUS: PASS


CHECK 7: SSH password відсутній в .env

grep -E '^NODES_NODA1_SSH_PASSWORD=' .env

Результат: 0 рядків (тільки коментар з поясненням)
STATUS: PASS


CHECK 8: secrets/ в .gitignore

grep 'noda1_id_ed25519' .gitignore

Результат: secrets/noda1_id_ed25519
STATUS: PASS


P1 — Router Config

CHECK 9: router-config.node2.yml не містить 172.17.0.1

grep '172.17.0.1' services/router/router-config.node2.yml

Результат: 0 рядків (тільки коментар # Version: 0.6.1 ... (no 172.17.0.1))
STATUS: PASS


CHECK 10: node2 compose монтує правильний config

grep 'router-config' docker-compose.node2-sofiia.yml

Результат: ./services/router/router-config.node2.yml:/app/router-config.yml:ro
STATUS: PASS


P1 — Port Binding

CHECK 11: Внутрішні порти на 127.0.0.1

grep -E '(9102|8890|8002):' docker-compose.node2-sofiia.yml

Результат:

- "127.0.0.1:9102:8000"
- "127.0.0.1:8890:8890"
- "127.0.0.1:8002:8002"

STATUS: PASS


Підсумок

Check Тест Статус
P0-1 /vision/models не порожній PASS
P0-2 Vision inference (llava-13b, ~3.5s) PASS
P0-3 Swapper healthy PASS
P1-4 SSH key auth до NODA1 PASS
P1-5 SSH_PASSWORD не в env контейнера ⚠️ PARTIAL (потрібен restart sofiia-console)
P1-6 SSH_PASSWORD не в compose (активний рядок) PASS
P1-7 SSH_PASSWORD не в .env PASS
P1-8 secrets/ в .gitignore PASS
P1-9 router-config.node2.yml без 172.17.0.1 PASS
P1-10 compose монтує node2 router config PASS
P1-11 Внутрішні порти на 127.0.0.1 PASS

Підсумок: 10/11 PASS, 1 PARTIAL (потрібен docker compose up -d)


Залишилось виконати

# 1. Перезапустити sofiia-console з новим compose (прибере password env)
docker compose -f docker-compose.node2-sofiia.yml up -d --no-deps sofiia-console

# 2. Перезапустити router з node2-specific config
docker compose -f docker-compose.node2-sofiia.yml up -d --no-deps router

# 3. Верифікація після restart
docker inspect sofiia-console --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -i 'ssh'
# Очікуємо: NODES_NODA1_SSH_PRIVATE_KEY=/run/secrets/noda1_ssh_key (і НЕ SSH_PASSWORD)