docs(vault-sync): acl fix closed 236/236 INHERIT+WRITE, watchdog cron, root cause hermes-taiga
This commit is contained in:
1 parent
8b831a85a1
commit
afbf895e2e
2 files changed
+154
-8
No files matched your search
@@ -15,7 +15,100 @@ namespace: family
|
||||
> 🔴 **РЕЦИДИВ 2026-09-22** — дефект вернулся (35 root-каталогов), наследование не защитило.
|
||||
> Плюс важный урок: **собирать dacl «с нуля» нельзя** — TrueNAS требует поле `id` в
|
||||
> каждой ACE, работает только read-modify-write. См. раздел «РЕЦИДИВ 2026-09-22» ниже.
|
||||
> **Статус: ОТКРЫТ** (синк сломан, фикс v2 готов но не применён).
|
||||
> ✅ **ПОЧИНЕНО 2026-09-22 (закрыто).** 236/236 каталогов: `INHERIT` + `WRITE`. Push прошёл
|
||||
> end-to-end (`ba3780c..8b831a8 main -> main`). Установлен cron-сторож (каждые 2 ч).
|
||||
> См. раздел «✅ ФИНАЛЬНЫЙ ФИКС 2026-09-22» в конце.
|
||||
|
||||
## ✅ ФИНАЛЬНЫЙ ФИКС 2026-09-22 (закрыто)
|
||||
|
||||
**Результат:**
|
||||
```
|
||||
INHERIT = 236/236 (все objects/XX)
|
||||
WRITE = 236/236 (write-тест в каждый каталог)
|
||||
root-owned каталогов: 35 — владелец root, но write-тест OK=35 FAIL=0 (группа 950 имеет права)
|
||||
git push с Mac: ba3780c..8b831a8 main -> main ✅
|
||||
```
|
||||
|
||||
### 🔴 Главный урок: `setacl` асинхронный — надо ЖДАТЬ job
|
||||
|
||||
Провал нескольких прогонов был из-за **гонки**: скрипт вызывал `setacl`, сразу читал
|
||||
`getacl` и видел **старые** флаги (`NOINHERIT`) → ложный `fail`. На самом деле job
|
||||
выполнялся через 1–3 сек и флаги применялись.
|
||||
|
||||
```python
|
||||
out = midclt("filesystem.setacl", arg) # → job id
|
||||
jid = int(out)
|
||||
while time.time() < deadline:
|
||||
j = json.loads(midclt("core.get_jobs", f'[["id","=",{jid}]]'))
|
||||
if j[0]["state"] in ("SUCCESS","FAILED","ABORTED"): break
|
||||
time.sleep(1)
|
||||
# ТОЛЬКО ТЕПЕРЬ читать getacl
|
||||
```
|
||||
|
||||
**Признак гонки:** `fixed=0`, `already=N`, `fail=M` — setacl «прошёл», флаги «не изменились».
|
||||
|
||||
### Рабочая структура ACL (после фикса)
|
||||
|
||||
```json
|
||||
{"tag":"owner@", "id":-1, "perms":{"BASIC":"FULL_CONTROL"}, "flags":{"BASIC":"INHERIT"}, "type":"ALLOW"}
|
||||
{"tag":"group@", "id":-1, "perms":{"READ_DATA":true,"WRITE_DATA":true,...}, "flags":{"BASIC":"INHERIT"}, "type":"ALLOW"}
|
||||
{"tag":"everyone@","id":-1, "perms":{"READ_DATA":true,"WRITE_DATA":true,...}, "flags":{"BASIC":"INHERIT"}, "type":"ALLOW"}
|
||||
```
|
||||
|
||||
🔴 **Флаги задаются как `{"BASIC":"INHERIT"}`, НЕ как булев dict**
|
||||
(`{"FILE_INHERIT":True,"DIRECTORY_INHERIT":True}`). Первая попытка с булевым dict
|
||||
отклонена: `[EINVAL] ... missing required keys(s): {'id'}` — потому что при неверном
|
||||
формате TrueNAS пересобирает ACE и теряет `id`. Замена `NOINHERIT` → `INHERIT` в
|
||||
существующем ACE работает.
|
||||
|
||||
🔴 **`getacl` возвращает `uid:0, gid:950` для root-owned каталогов, но `perms.BASIC` с
|
||||
`FULL_CONTROL` — и запись от uid 950 проходит через `group@` (gid 950).** Владелец root
|
||||
сам по себе не блокирует.
|
||||
|
||||
### Перманентность — проверена ФАКТОМ
|
||||
|
||||
```bash
|
||||
mkdir objects/zzt # новый каталог
|
||||
midclt call filesystem.getacl .../objects/zzt
|
||||
# → owner@/group@/everyone@: FILE_INHERIT:True, DIRECTORY_INHERIT:True, INHERITED:True ✅
|
||||
touch objects/zzt/.wt # → OK ✅
|
||||
```
|
||||
|
||||
**Новый `objects/XX` наследует права автоматически.** Баг не вернётся даже при
|
||||
root-владельце, потому что ACL родителя уже с INHERIT.
|
||||
|
||||
### Сторож от рецидива
|
||||
|
||||
```
|
||||
~/scripts/vault-acl-watchdog.py (на TrueNAS)
|
||||
cron: 0 */2 * * * /usr/bin/python3 ~/scripts/vault-acl-watchdog.py >> ~/scripts/vault-acl-watchdog.log 2>&1
|
||||
```
|
||||
|
||||
Поведение: **SILENT если всё ок**; если нашёл сломанный каталог — чинит (setacl + ожидание
|
||||
job) и печатает отчёт. Запуск от `truenas_admin` (uid 950) — `midclt` ему доступен как
|
||||
FULL_ADMIN, root-пароль не нужен.
|
||||
|
||||
### 🔴 Осталось (корень НЕ устранён)
|
||||
|
||||
Контейнер `hermes-taiga` (второй Hermes на TrueNAS) работает **от root**:
|
||||
|
||||
```
|
||||
f3f36f1eb745 hermes-taiga:latest
|
||||
└─ uv run hermes gateway run (root)
|
||||
└─ mcpvault /vault (root) → создаёт root-owned objects/XX
|
||||
compose: /mnt/RED_2TB/docker/hermes/docker-compose.yml
|
||||
env: HERMES_ALLOW_ROOT_GATEWAY=1 ← явное разрешение root
|
||||
User: (пусто) = root
|
||||
mounts: /mnt/RED_2TB/storage/git/obsidian-vault.git → /vault.git
|
||||
```
|
||||
|
||||
**Перманентное устранение корня:** добавить `user: "950:950"` в `taiga` service этого
|
||||
compose → mcpvault пишет от 950 → root-объектов нет вообще.
|
||||
|
||||
**Риск:** контейнер может не стартовать, если образ требует root для `/opt/data`.
|
||||
Требует перезапуска `hermes-taiga` (второй инстанс отключится на ~минуту).
|
||||
**Не сделано** — чужой контейнер, нужно явное решение Alex. Сторож пока закрывает
|
||||
последствия автоматически.
|
||||
|
||||
## Симптом
|
||||
|
||||
@@ -151,12 +244,9 @@ setacl({"path": path, "dacl": dacl,
|
||||
|
||||
## Remaining (открытые вопросы)
|
||||
|
||||
0. 🔴 **2026-09-22 РЕЦИДИВ НЕ УСТРАНЁН.** Синк сломан, push с Mac падает. Кол-во root-каталогов
|
||||
вернулось (35). Фикс v2 (`/tmp/fix_vault_acl2.py` на Mac, read-modify-write) **написан, но не
|
||||
залит и не запущен** — Alex: «сначала доки, потом чинить синк».
|
||||
**Порядок возобновления:** `scp` скрипта на TrueNAS → запуск → проверка `touch` в
|
||||
`objects/XX` → `git push nas main`. Скрипт v1 (`fix_vault_acl_inherit.py`) **нерабочий**,
|
||||
удалить/не использовать (`[EINVAL] … missing required keys(s): {'id'}`).
|
||||
0. ~~**2026-09-22 РЕЦИДИВ НЕ УСТРАНЁН.**~~ → **УСТРАНЁН 2026-09-22**, см. раздел
|
||||
«✅ ФИНАЛЬНЫЙ ФИКС 2026-09-22» выше. Скрипт v1 (`fix_vault_acl_inherit.py`) — нерабочий
|
||||
(булев dict флагов без `id`), заменён на read-modify-write + ожидание job.
|
||||
1. ~~**Наследование не проверено на практике**~~ — **проверено 2026-09-21 15:05 UTC** (read-only с Taiga), см. раздел «Верификация наследования» ниже. Наследование работает **на тот момент**; 2026-09-22 показал, что от рецидива оно НЕ спасает.
|
||||
2. **`mcpvault` продолжает работать от root** — пока он root, дефект может вернуться. Профилактика: перезапустить его под uid 950.
|
||||
3. **`cleanup` не видит `/media/movies`** — на Кра́кене удаляются только Radarr-файлы; просмотренное лежит в `/media/movies`, диск будет расти. Отдельная задача (см. `family/plans/watchlist-disk-overflow-fix.md`).
|
||||
|
||||
Reference in new issue
Block a user