[2026-09-02] eagle: family/documents/vault-sync/2026-09-02-hermes-taiga-crashloop.md family/how-to/vault-git-sync.md
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
---
|
||||
tags: [truenas, hermes, taiga, crashloop, syncthing, vault-sync, incident]
|
||||
created: 2026-09-02
|
||||
updated: 2026-09-02
|
||||
status: open — root cause identified, fix NOT yet applied (ждёт Alex)
|
||||
---
|
||||
|
||||
# Incident 2026-09-02: hermes-taiga crash-loop (16 339 рестартов) — Taiga git-sync стоит с авг, телефон видит устаревший vault
|
||||
|
||||
**Родительские контексты:** [[2026-08-31-syncthing-truenas-incident]], [[2026-09-02-restore-privilege-scope]]. Здесь документируем свежую поломку: контейнер `hermes-taiga` упал в бесконечный restart-loop, из-за чего 3-phase Taiga git-sync **не выполняется**, и обе Taiga-копии vault (`/vault` и `/obsidian-syncthing`) отстали от bare repo **на месяц**.
|
||||
|
||||
**Симптом (жалоба Alex, «syncthing state не совпадает с маком/гитом»):** состояние папки Syncthing для телефона не совпадает с Mac / с тем, что запушено в git.
|
||||
|
||||
---
|
||||
|
||||
## Диагноз по цепочке (проверено 2026-09-02)
|
||||
|
||||
| Сторона | Состояние | HEAD |
|
||||
|---|---|---|
|
||||
| Mac `~/obsidian` | ✅ синхронен с bare repo (ahead=0/behind=0) | `2fab879` (2026-09-02) |
|
||||
| Bare repo `obsidian-vault.git` (истина) | ✅ источник | `2fab879` (2026-09-02) |
|
||||
| TrueNAS Syncthing P2P → телефон | ✅ работает (folder `k5vyy-gzdgj` «Obsidian Vault», up 2 days healthy) | — |
|
||||
| **Taiga `/storage/obsidian-syncthing`** | ⛔ **отстал на месяц** | `ceea848` (2026-08-01) |
|
||||
| **Taiga `/storage/obsidian`** | ⛔ **отстал на месяц** | `ceea848` (2026-08-01) |
|
||||
|
||||
**Корень (проверено):** контейнер `hermes-taiga` в **crash-loop — `Restarts=16339`**, `StartedAt` постоянно сбрасывается. Логи: на каждом старте `uv` пытается докачать зависимости `pytz`, `markdown-it-py` с PyPI → **`client error (Connect) / operation timed out`** → `uv run` падает → `restart: unless-stopped` → без конца. `hermes` binary при этом даже не стартует (`docker exec ... hermes` → `executable file not found in $PATH` — потому что venv в /tmp пуст/недоустановлен).
|
||||
|
||||
### Почему `uv` качает на каждом старте + почему тайм-аутит
|
||||
|
||||
**Проблема 1 — маршрут через мёртвый прокси.** Активный compose `/mnt/RED_2TB/docker/hermes/docker-compose.yml` задаёт:
|
||||
```yaml
|
||||
environment:
|
||||
- HTTP_PROXY=socks5://vless-proxy:1080
|
||||
- HTTPS_PROXY=socks5://vless-proxy:1080
|
||||
- UV_CACHE_DIR=/tmp/uv-cache
|
||||
- NO_PROXY=portainer-mcp,homeassistant,localhost,127.0.0.1
|
||||
```
|
||||
Весь исходящий HTTP (вкл. PyPI для `uv`) идёт через `socks5://vless-proxy:1080`. А **outbound `vless-proxy` мёртв** (см. `truenas-infrastructure.md` шапка: `v.qentra.top` удалён, DNS остался в Cloudflare → трафик из прокси наружу не выходит). ⇒ `uv` не может скачать депы → timeout.
|
||||
|
||||
**Проблема 2 — `UV_CACHE_DIR=/tmp/uv-cache`, а не впекённый venv.** Образ `hermes-taiga:latest` собран 2026-08-24 (`FROM node:20-slim`, entrypoint `["uv","run","hermes","gateway","run"]`, в Dockerfile при build идёт `uv pip install -e ".[all]"`). Но compose перенаправляет uv-кэш в `/tmp/uv-cache` (tmpfs контейнера), который **обнуляется на каждый рестарт** → при каждом старте `uv run` пере-синхронизирует депы → опять PyPI → опять timeout. Порочный круг. (Вместе с тем контейнер смонтирован с настоящей конфигой в `config/`, а деps НЕ должен перекачивать при здоровом образе/запуске.)
|
||||
|
||||
### Контейнер hermes-taiga (для справки)
|
||||
|
||||
- Image: `hermes-taiga:latest`, `container_name: hermes-taiga`, `restart: unless-stopped`
|
||||
- Entrypoint (в образе): `["uv","run","hermes","gateway","run"]`
|
||||
- WorkingDir: `/opt/hermes`
|
||||
- Mounts (compose активный):
|
||||
- `/mnt/RED_2TB/storage/obsidian-syncthing -> /obsidian-syncthing:rw` (полная копия, phone)
|
||||
- `/mnt/RED_2TB/storage/obsidian -> /vault:rw` (sparse)
|
||||
- `/mnt/RED_2TB/storage/git/obsidian-vault.git -> /vault.git`
|
||||
- `/mnt/RED_2TB/docker/hermes/config -> /opt/data`
|
||||
- Env: `HERMES_ALLOW_ROOT_GATEWAY=1`, `UV_CACHE_DIR=/tmp/uv-cache`, `HTTP_PROXY/HTTPS_PROXY=socks5://vless-proxy:1080`, `NO_PROXY=...`; `env_file: .env`
|
||||
- Сети: `taiga_net` (внутр) + `ha_net`(external `ha_default`); `depends_on: portainer-mcp (healthy)`
|
||||
|
||||
> В `/mnt/RED_2TB/docker/hermes/` есть **второй, Новый Dockerfile** в `build/Dockerfile` (debian:13, multi-stage uv/gosu, `COPY .`, `uv pip install --no-cache-dir -e ".[all]"`, `chmod a+rX`, свой `/entrypoint.sh`, `HERMES_WEB_DIST`), а в корне — **Старый активный Dockerfile** (`node:20-slim`, клонирует upstream, entrypoint `uv run`). Активный compose ссылается на старый (`context: ., dockerfile: Dockerfile`). Это наследие расхождения build/каноне — кандидат на консолидацию, но осторожно.
|
||||
|
||||
### Почему это ломает vault-sync
|
||||
|
||||
Taiga 3-phase sync (`~/sync-vault.sh`, Hermes cron) запускается **внутри агента hermes-taiga**. Раз агент в crash-loop и `hermes` не стартует → cron не выполняется → **оба Taiga-клиента не тянут из bare repo с ~2026-08-01**. Телефон (Syncthing-копия `obsidian-syncthing`) продолжает синкаться P2P с тем, что там застряло (старое), а git-история Mac/bare repo ушла вперёд → рассинхрон, который видит Alex.
|
||||
|
||||
**⚠️ Ситуация с `file:///vault.git` / bare repo:** bare repo в порядке (2fab879). Просто Taiga-клиенты не делают fetch/merge с августа. Это НЕ поломка прав (та уже решена 2026-09-02), а именно мёртвый агент.
|
||||
|
||||
---
|
||||
|
||||
## ЧТО ЕЩЁ НЕ ДЕЛАЛОСЬ (остаток — конец сессии)
|
||||
|
||||
Диагностика остановилась на идентификации корня. **Фикс НЕ применён** (read-only проверка venv/прокси не прошла — подтверждение Alex истекло). Не сделано:
|
||||
1. Проверка полноты `.venv` в образе `hermes-taiga:latest` (throwaway-контейнер read-only): есть ли `pytz`/`markdown-it-py`/`hermes_cli`.
|
||||
2. Проверка живости `vless-proxy` изнутри (fetch через socks5).
|
||||
3. Выбор и применение фикса (см. ниже).
|
||||
|
||||
---
|
||||
|
||||
## Варианты фикса (к обсуждению, НЕ внедрено)
|
||||
|
||||
**Ключевая развилка — связь Taiga с внешним миром.** Taiga (в отличие от Kraken) **нужна сеть наружу** (web, Telegram через API). Раз `vless-proxy` мёртв, вопрос: восстановить прокси-выход или дать Taiga прямой egress. На TrueNAS есть рабочий Xray-сервер на `vpn.mallexxx.duckdns.org:443` (`xray-admin`, client `user1` direct) — можно нацелить прокси Taiga на него. Подробно прокси-инфра: `family/how-to/truenas-infrastructure.md`.
|
||||
|
||||
Непосредственно краш-луп чинить, чтобы агент поднялся:
|
||||
- **Убрать зависимость startup от PyPI:** сборка образа должна впекять полный venv и не делать `uv run`-reinstall на старте (перейти на улучшенный `build/Dockerfile` с `/entrypoint.sh`), И/ИЛИ убрать `/tmp/uv-cache` в пользу персистентного кэша на `config/` (bind mount `/opt/data`).
|
||||
- **Восстановить прокси:** обновить outbound `vless-proxy` на рабочий endpoint (`vpn.mallexxx.duckdns.org`, user1) или убрать `HTTP(S)_PROXY` если прокси не обязателен для Taiga (тогда `uv` сходит на PyPI напрямую с TrueNAS).
|
||||
|
||||
После подъёма агента — **ручной прогон 3-phase sync** чтоб Taiga-копии догнать до bare repo и телефон получил актуальное состояние:
|
||||
```bash
|
||||
ssh truenas_admin@mallexxx.duckdns.org "bash ~/sync-vault.sh" # 3-phase (syncthing→vault→syncthing)
|
||||
```
|
||||
Проверка догона:
|
||||
```bash
|
||||
ssh truenas_admin@mallexxx.duckdns.org 'for d in /mnt/RED_2TB/storage/obsidian /mnt/RED_2TB/storage/obsidian-syncthing; do echo "== $d"; git -C "$d" rev-list --left-right --count main...origin/main; git -C "$d" log -1 --format="%h %ci %s"; done'
|
||||
```
|
||||
|
||||
> ⚠️ В `obsidian-syncthing` есть **живые телефонные незакоммиченные изменения** (`.stversions/...`, `altai-build-checklist.md` и др.) — при ручном мерже вручную не затереть входящее с телефона (штатный 3-way merge в sync-vault-lib это учитывает).
|
||||
|
||||
---
|
||||
|
||||
## Связанные заметки
|
||||
- [[truenas-infrastructure]] — шапка: vless-proxy outbound мёртв; Hermes-Taiga раздел
|
||||
- [[vault-git-sync]] / [[obsidian-sync]] — архитектура sync и его сценарии
|
||||
- [[syncthing-truenas-android]] — syncthing-копия и её mount
|
||||
- [[2026-08-31-syncthing-truenas-incident]] — родитель: поломка прав syncthing-папки (другая, решена)
|
||||
- [[2026-09-02-restore-privilege-scope]] — родитель: поломка прав после restore (решена)
|
||||
@@ -12,7 +12,9 @@ tags:
|
||||
|
||||
# Vault Git Sync
|
||||
|
||||
> **STATE 2026-09-02:** Eagle (мой `~/obsidian`) — git-sync **СТОИТ**: `main...nas/main [ahead 55]`. Причина — поломка прав после restore: `/mnt/RED_2TB/storage/git` (bare repo `obsidian-vault.git`) → `d--------- 921 921` (uid 921 = transmission). SSH к TrueNAS живой, но `git fetch`: `fatal: ... does not appear to be a git repository`. Fix: `chown 950:950` + `chmod u+rwX,g+rwX` на `storage/git`, затем `bash ~/scripts/sync-vault.sh`. Подробно: `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`.
|
||||
> **STATE 2026-09-02 (позднее обновление):** Eagle/bare repo снова **синхронны** (ahead=0/behind=0, `2fab879`). Ранее (см. ниже) git-sync стоял из-за битых прав `storage/git` — **починено** полной dacl-заменой (`family/documents/vault-sync/2026-09-02-restore-privilege-scope.md` §RESOLVED).
|
||||
>
|
||||
> **⛔ НОВАЯ проблема 2026-09-02 (не решена):** оба **Taiga-клиента** (`/storage/obsidian` и `/storage/obsidian-syncthing`) **отстали на месяц** — HEAD `ceea848` (2026-08-01) vs bare repo `2fab879` (2026-09-02). Причина: контейнер `hermes-taiga` в **crash-loop** (16339 рестартов) — `uv run hermes gateway run` не может докачать депы (pytz/markdown-it-py) с PyPI, т.к. весь HTTP идёт через **мёртвый `socks5://vless-proxy:1080`**, а `UV_CACHE_DIR=/tmp/uv-cache` пустеет на каждом рестарте. Taiga 3-phase sync (крон внутри агента) не выполняется => телефон видит устаревший vault. Подробно: `family/documents/vault-sync/2026-09-02-hermes-taiga-crashloop.md`. Фикс НЕ применён (ждёт Alex).
|
||||
|
||||
> **Триггер cron на маке (Eagle) — это launchd, НЕ Hermes cron:** `~/Library/LaunchAgents/com.sync-vault.plist` → `/Users/admin/scripts/sync-vault.sh`, `StartInterval=300` (5 мин). Скрипт `sync-vault-lib.sh` намеренно глушит dead remote (`git fetch` fail → `exit 0`), поэтому launchd показывает `last exit code = 0` даже при фактически стоящем sync. Системный crontab на маке пуст.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user