Files
obsidian-vault/family/documents/vault-sync/2026-09-26-syncthing-clone-root-objects-acl-confusion.md
T

200 lines
12 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 <path>` (`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`