--- title: obsidian-syncthing — root-owned objects + битый remote + путаница ACL/chown type: log namespace: family tags: [vault, sync, syncthing, git, permissions, acl, nfsv4, root] date: 2026-09-26 status: resolved --- # `obsidian-syncthing`: 4031 root-объект, битый remote, ACL/chown не стоит **Когда:** 2026-09-26, разбор по запросу Alex «почему документ не доехал до телефона». **Статус:** ✅ **РЕШЕНО** — ACL с `nas_users` + INHERIT применён, синк работает (см. «РЕШЕНИЕ» ниже). ## Симптом Нота `personal/plans/music-tags-review/1-needs-decision.md` закоммичена и запушена с Mac (`66d4d62..f2501dc main -> main`), но в клон `/obsidian-syncthing` на TrueNAS **не попала**. `git pull` в клоне падает, а `sync-vault.sh` глушит ошибку (`2>/dev/null`) — синк выглядит успешным. ## Две независимые поломки ### 1. Битый remote в клоне (починено в этой сессии) ``` было: origin /vault.git ← потерян префикс пути стало: origin /mnt/RED_2TB/storage/git/obsidian-vault.git ``` `git fetch` при этом падал с `fatal: '/vault.git' does not appear to be a git repository`. Remote переписан через `git remote set-url`. **Это не связано с правами** — отдельный дефект. ### 2. Права: новые объекты пишет root (НЕ починено) ``` объекты от root: 4051 ← свежие, 2026-09-26 02:42 объекты от truenas_admin: 4 ← только старые pack с 2026-07-06 ``` `git fetch` падает на записи: ``` error: insufficient permission for adding an object to repository database .git/objects fatal: failed to write object fatal: unpack-objects failed ``` **Причина:** контейнер `hermes-taiga` работает **от root** (`docker inspect` → `Config.User` пусто, `docker exec ... id` → `uid=0(root)`). Именно он делает `git pull` в `/obsidian-syncthing` — значит каждый новый loose-объект рождается `root:root`, а git под `truenas_admin` (uid 950) писать в них не может. ## ACL на `obsidian-syncthing` НЕ СТОИТ — `trivial_acl: true` ``` nfs4xdr_getfacl /mnt/RED_2TB/storage/obsidian-syncthing # owner: 950 # group: 950 # mode: 0o40770 # trivial_acl: true ← расширенного ACL нет owner@:rwxpD-aARWcCos:-------:allow group@:rwxpD-a-R-c--s:-------:allow everyone@:------a-R-c--s:-------:allow ``` Только дефолтный набор TrueNAS (`owner@` / `group@` / `everyone@`), **ни одной именованной записи**. POSIX-вид (`getfacl`) показывает `user::rwx group::rwx other::---` и **скрывает** отсутствие расширенного ACL — поэтому диагностировать надо `nfs4xdr_getfacl`, а не `getfacl`. ## 🔴 Путаница: ACL ставился на `Edu`, не на `obsidian-syncthing` Alex помнил, что фикс ACL уже делался («ты вроде ставил рекурсивный acl а не chown»). Проверка по базе Hermes (`state.db`, таблица `messages`) нашла сессию **`20260923_124118_9e70782e` (2026-09-23)** — там рекурсивный ACL **действительно ставился**, но на **`/mnt/RED_2TB/Edu`**, по прямой просьбе Alex: «ты можешь просто группу под acl сделать с inherit чтобы весь edu был доступен группе включающей truenas_admin?» Что тогда было сделано (и сработало — на `Edu`): ```bash # 1. бэкап ACL midclt call filesystem.getacl /mnt/RED_2TB/Edu > .../acl-edu-before-YYYYmmdd-HHMMSS.json # 2. setacl recursive: gid -> 3000 (nas_users) + INHERIT на всех ACE → job SUCCESS # 3. chgrp -R nas_users → FAILED (Operation not permitted) # 4. повтор через midclt setacl с uid/gid=3000 → job 15393 SUCCESS ``` Результат на `Edu`: `drwxrwxr-x root:nas_users`, `gid=3000`, все ACE `INHERITED: True`, `touch` → WRITE_OK. **Группа `nas_users` (gid 3000)** — рабочая: в ней `truenas_admin`, `mallexxx`, `nas`, `root`, `transmission`. > ⚠️ **Урок: «ACL уже ставили» ≠ «ACL стоит на этой папке».** Правка была на `Edu`. > На `obsidian-syncthing` расширенного ACL **не было никогда** (`trivial_acl: true` доказывает). > Прежде чем повторять «известный фикс» — проверить, что он на **той самой** папке. > 🔴 **`chgrp` от `truenas_admin` даёт `Operation not permitted`.** В NFSv4 `group@` — это > POSIX-gid файла, а не ACE. Без смены gid группа не получает ничего. Менять gid надо через > `midclt filesystem.setacl` (root-контекст), а не `chgrp`/`chown` из шелла. ## ✅ РЕШЕНИЕ (2026-09-26, после требования Alex «Да, ставь acl inherit») Alex отверг предложенные варианты и дал прямую команду: **«Да, ставь acl inherit»**. Выбран **вариант A** — ACL + INHERIT, применён на `/mnt/RED_2TB/storage/obsidian-syncthing`. **Что сделано (по порядку):** ```bash # 1. бэкап ACL midclt call filesystem.getacl /mnt/RED_2TB/storage/obsidian-syncthing \ > /home/truenas_admin/variantA_bk/acl-obsidian-syncthing-before-20260926-154827.json # 2. скрипт read-modify-write (файлом, не инлайном) → scp на NAS → python3 # payload: gid=3000 (nas_users), uid=950, recursive=true, # все ACE → FILE_INHERIT+DIRECTORY_INHERIT, stripacl=false # → job 25046 SUCCESS # 3. remote клона git remote set-url origin /mnt/RED_2TB/storage/git/obsidian-vault.git ``` **Результат (проверено ФАКТОМ):** | | До | После | |---|---|---| | `nfs4xdr_getfacl` | `trivial_acl: true` | **`trivial_acl: false`** | | `group` | 950 | **3000** (`nas_users`) | | флаги ACE | `-------` (NOINHERIT) | **`fd-----`** (FILE+DIRECTORY_INHERIT) | | объекты от root | 4051 | **0** (все 4073 = `truenas_admin`) | | `git fetch` | падал | `Already up to date` | | новый файл `touch` | — | `truenas_admin:nas_users` ✅ | **Наследование подтверждено:** `touch .inherit_test` и `mkdir .inherit_dir_test` внутри папки получили `truenas_admin:nas_users` (тестовые артефакты удалены после проверки). **Нота доехала:** коммит с Mac `f2501dc` (`1-needs-decision.md`, разбор 28 файлов) найден в истории клона, поверх уже лежал `8efe5c8` от Taiga. ### 🔴 ГЛАВНЫЙ ПИТФОЛЛ: `midclt getacl` = КЭШ Сразу после `setacl` скрипт делал верификацию через `midclt filesystem.getacl` — и получал **старые** значения (`trivial: True`, `gid: 950`, `NOINHERIT`), печатая ложный «VERIFY FAILED». Правка на диске при этом была уже применена. > **Реальное состояние проверять только:** `nfs4xdr_getfacl ` (`trivial_acl: false`, > флаги `fd-----`) + `stat -c '%A %U:%G %n'` + фактический `touch` нового файла. > **Не откатывать и не повторять `setacl` по показаниям `getacl`.** ### Альтернативный вариант B (не использован, для истории) `user: "950:950"` в taiga service — устранил бы корень (контейнер не от root), но риск: образ может требовать root для `/opt/data`. Оставлен как возможное усиление; текущий ACL-INHERIT закрывает последствия. ## ℹ️ Почему однократный `chown` не лечил (историческая справка) Прошлый разовый `chown` объектов на `truenas_admin` чинил только **уже существующие** объекты. Следующий `git pull` от root снова рождал root-owned объекты — и `chown` приходилось повторять. **Это лечение симптома.** Перманентный фикс — либо `ACL + INHERIT` (новые объекты наследуют права группы), либо запуск синка **не от root** (`user: "950:950"` в taiga service). ## Что предлагается (решение за Alex) | Вариант | Как | Плюс / минус | |---|---|---| | **A. ACL + INHERIT** | `setfacl`/`midclt setacl` с `g:truenas_admin:rwx` + `d:` (default) + `chmod g+s` | root и uid 950 пишут одновременно; нужен контроль, что TrueNAS не сбросит ACL при операциях датасета | | **B. Контейнер не от root** | `user: "950:950"` в taiga service `/mnt/RED_2TB/docker/hermes/docker-compose.yml` | устраняет корень; риск — образ может требовать root для `/opt/data` | | **C. Повторный `chown`** | перед каждым pull | НЕ рекомендуется — лечит симптом | ## Сопутствующий дефект: скрипт глушит ошибки `sync-vault.sh` / `sync-vault-lib.sh` вызывают `git fetch` и `git merge` с `2>/dev/null`. При падении синк рапортует **«Pushed ✓» / exit 0**, хотя pull не прошёл. Это и скрывало поломку. Предложение — убрать `2>/dev/null` с `fetch`/`merge`, чтобы падение было видно в логе (та же логика, что уже описана для launchd: `exit code 0` ≠ «синк прошёл»). ## Диагностика (воспроизвести) ```bash # владельцы объектов в клоне ssh truenas_admin@mallexxx.duckdns.org \ "cd /mnt/RED_2TB/storage/obsidian-syncthing && find .git/objects -type f -printf '%u\n' | sort | uniq -c" # реальный ACL (NFSv4, не POSIX!) nfs4xdr_getfacl /mnt/RED_2TB/storage/obsidian-syncthing # trivial_acl: true? # под кем реально работает контейнер docker inspect hermes-taiga --format '{{.Config.User}}' # пусто => root docker exec hermes-taiga id # uid=0(root) # remote клона cd /mnt/RED_2TB/storage/obsidian-syncthing && git remote -v ``` ## Связанные документы - `family/how-to/vault-git-sync.md` — архитектура и питфоллы синка - `family/documents/vault-sync/2026-09-21-bare-repo-push-permission-denied.md` — тот же root-инстанс Hermes, но на **bare repo** - `family/documents/vault-sync/2026-09-26-mode-flip-644-755.md` — шум прав от Syncthing - `personal/tech/truenas-administration` (skill) — NFSv4 ACL через `midclt`